核心数据获取值的总和。获取性质与传播 [英] Core Data get sum of values. Fetched properties vs. propagation

查看:134
本文介绍了核心数据获取值的总和。获取性质与传播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Core Data比较陌生(来自SQLite背景)。刚刚完成阅读核心数据iOS书,但我有很多令人困惑的问题,当我开始建模具有以下模型的应用程序:


  1. 具有一对多交易关系和一个startingBalance属性的帐户实体


  2. $







    出于性能原因,我想反模式化模型,并在帐户实体中添加一个TotalAmountSpent属性(如本书所建议的),以便在更改时可以随时更新。 / p>

    在实践中,这似乎很难用Core Data实现。我不知道如何正确地做这个(不知道什么是正确的方法)。所以我的问题是:



    a)我应该将TotalAmountSpent改为Fetched属性吗?是否有性能影响(我知道它是懒惰加载,但我几乎肯定会获取每个帐户的属性)。如果我这样做,我需要能够得到在一个给定的时间段(例如最后三天)startingBalance花费的总金额。这似乎很容易在SQL,但我如何在Core Data中这样做?我读我可以使用@sum聚合函数,但是如何使用@sum过滤'date'?我也读取数据中的任何更改将需要刷新获取的属性。我如何听变化?我在付款实体的willSave方法中执行吗?



    b)我应该使用传播并手动更新'TotalAmountSpent'交易?什么是最好的地方这样做?我应该在一个重写的NSManagedObject的'willSave'方法吗?我恐怕如果帐户上的startingBalance字段更新,更新所有相应的交易/付款将是一场噩梦。然后,我必须加载每笔付款,并计算总金额和帐户的最终余额。可怕的是有成千上万的付款



    任何关于这个问题的指导都会非常感激。谢谢!

    解决方案

    如果您使用获取的属性,那么无法首先将数据加载到内存中,因此,我建议您在实体中保留实际的非标准化数据。



    实际上有几种方法可以轻松保持此更新。


    1. 在您的 -awakeFromFetch / -awakeFromInsert 设置将影响值的关系的观察者。然后当KVO(键值观察者)触发时,您可以进行计算和更新字段。学习KVC和KVO是一项有价值的技能。


    2. 您可以覆盖<$ c $中的 -willSave $ c> NSManagedObject 子类并对保存进行计算。虽然这更容易,但我不推荐它,因为它只是在保存时触发,并且不能保证您的帐户对象将被保存。


    在这两种情况下,您都可以使用 KVC收集操作员。使用收集操作符,您可以通过调用:

      NSNumber * sum = [self valueForKeyPath:@transactions。 @ sum.startingBalance]; 


    I'm relatively new to Core Data (coming from an SQLite background). Just finished reading the 'Core Data for iOS' book but I'm left with a number of baffling questions when I started modelling an app which has the following model:

    1. 'Accounts' entity which has a to-many 'transactions' relationship and a 'startingBalance' property
    2. 'Transaction' entity which has a to-many 'payments' relationship (and an inverse to Accounts)
    3. 'Payment' entity which contains details of the actual 'amount' paid

    For performance reasons I wanted to de-normalize the model and add a 'TotalAmountSpent' property in the 'Accounts' entity (as suggested by the book) so that I could simply keep updating that when something changed.

    In practice this seems difficult to achieve with Core Data. I can't figure out how to do this properly (and don't know what the right way is). So my questions are:

    a) Should I change the 'TotalAmountSpent' to a Fetched Property instead? Are there performance implications (I know it's loaded lazily but I will almost certainly be fetching that property for every account). If I do, I need to be able to get the total amount spent against the 'startingBalance' for a given period of time (such as the last three days). This seems easy in SQL but how do I do this in Core Data? I read I can use a @sum aggregate function but how do I filter on 'date' using @sum? I also read any change in the data will require refreshing the fetched property. How do I 'listen' for a change? Do I do it in 'Payment' entity's 'willSave' method?

    b) Should I use propagation and manually update 'TotalAmountSpent' each time a new payment gets added to a transaction? What would be the best place to do this? Should I do it in an overridden NSManagedObject's 'willSave' method? I'm then afraid it'll be a nightmare to update all corresponding transactions/payments if the 'startingBalance' field was updated on the account. I would then have to load each payment and calculate the total amount spent and the final balance on the account. Scary if there are thousands of payments

    Any guidance on the matter would be much appreciated. Thanks!

    解决方案

    If you use a fetched property you cannot then query on that property easily without loading the data into memory first. Therefore I recommend you keep the actual de-normalized data in the entity instead.

    There are actually a few ways to easily keep this up to date.

    1. In your -awakeFromFetch/-awakeFromInsert set up an observer of the relationship that will impact the value. Then when the KVO (Key Value Observer) fires you can do the calculation and update the field. Learning KVC and KVO is a valuable skill.

    2. You can override -willSave in the NSManagedObject subclass and do the calculation on the save. While this is easier, I do not recommend it since it only fires on a save and there is no guarantee that your account object will be saved.

    In either case you can do the calculation very quickly using the KVC Collection Operators. With the collection operators you can do the sum via a call to:

    NSNumber *sum = [self valueForKeyPath:@"transactions.@sum.startingBalance"];
    

    这篇关于核心数据获取值的总和。获取性质与传播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆