我对Core Data相对较新(来自SQLite背景) . 刚读完“iOS的核心数据”一书,但当我开始为具有以下型号的应用程序建模时,我留下了一些令人困惑的问题:
-
'Accounts'具有多对多'transactions'关系和'startingBalance'属性的实体
-
'Transaction'具有多对多'payments'关系的实体(与Accounts相反)
-
'Payment'实体,其中包含实际'amount'已付款的详细信息
出于性能原因,我想对模型进行去规范化,并在“帐户”实体中添加“TotalAmountSpent”属性(如本书所示),这样我就可以在发生变化时继续更新 .
在实践中,这似乎很难通过Core Data实现 . 我无法弄清楚如何正确地做到这一点(并且不知道正确的方法是什么) . 所以我的问题是:
a)我应该将'TotalAmountSpent'更改为Fetched Property吗?是否有性能影响(我知道它是懒惰加载但我几乎肯定会为每个帐户获取该属性) . 如果我这样做,我需要能够在给定的时间段(例如最后三天)内获得花在'startingBalance'上的总金额 . 这在SQL中看起来很简单,但我如何在Core Data中执行此操作?我读过我可以使用@sum聚合函数但是如何使用@sum过滤'date'?我还读了数据中的任何变化都需要刷新fetched属性 . 我如何'倾听'改变?我是在“付款”实体的'willSave'方法中做到的吗?
b)每次将新的付款添加到交易时,我是否应该使用传播并手动更新“TotalAmountSpent”?最好的地方是什么?我应该在重写的NSManagedObject的'willSave'方法中做到吗?我担心,如果在帐户上更新了“startingBalance”字段,更新所有相应的交易/付款将是一场噩梦 . 然后我必须加载每笔付款并计算花费的总金额和帐户的最终余额 . 如果有数千笔付款可怕
任何关于此事的指导都将非常感激 . 谢谢!
1 回答
如果使用fetched属性,则无法在不首先将数据加载到内存中的情况下轻松查询该属性 . 因此,我建议您将实际的非规范化数据保留在实体中 .
实际上有几种方法可以轻松地保持最新状态 .
在您的
-awakeFromFetch
/-awakeFromInsert
中设置一个影响该值的关系的观察者 . 然后,当KVO(键值观察器)触发时,您可以进行计算并更新字段 . 学习KVC和KVO是一项宝贵的技能 .您可以覆盖
NSManagedObject
子类中的-willSave
并对保存进行计算 . 虽然这更容易,但我不推荐它,因为它只会在保存时触发,并且无法保证您的帐户对象将被保存 .在任何一种情况下,您都可以使用KVC Collection Operators非常快速地进行计算 . 通过集合运算符,您可以通过以下方式调用: