如何在 EF 中获取实体更改增量?
Posted
技术标签:
【中文标题】如何在 EF 中获取实体更改增量?【英文标题】:How to get entity change delta in EF? 【发布时间】:2011-12-14 17:44:03 【问题描述】:我只需要获取已更改字段的列表,数据存储是 ssce,因此没有可用的触发器
EF 是否支持获取列表或构建通用组件?
【问题讨论】:
【参考方案1】:根据上下文的类型和生成的实体,您可以通过几种不同的方式进行操作。
对于从 Entity 或 POCO 继承的对象,您可以使用 ObjectStateManager
如果是 Self-Tracking 实体,您可以使用实体本身的 Tracker。
请提供有关您如何生成上下文以及如何进行更改的更多详细信息
已编辑(2):
您可以像这样查询 ObjectStateManager
以获取更改的条目:
var changed = ctx.ObjectStateManager.GetObjectStateEntries().Where(e=>e.State != EntityState.Unchanged);
已编辑(1):
MSDN 中的以下示例演示了如何查询更改:
int orderId = 43680;
using (AdventureWorksEntities context =
new AdventureWorksEntities())
var order = (from o in context.SalesOrderHeaders
where o.SalesOrderID == orderId
select o).First();
// Get ObjectStateEntry from EntityKey.
ObjectStateEntry stateEntry =
context.ObjectStateManager
.GetObjectStateEntry(((IEntityWithKey)order).EntityKey);
//Get the current value of SalesOrderHeader.PurchaseOrderNumber.
CurrentValueRecord rec1 = stateEntry.CurrentValues;
string oldPurchaseOrderNumber =
(string)rec1.GetValue(rec1.GetOrdinal("PurchaseOrderNumber"));
//Change the value.
order.PurchaseOrderNumber = "12345";
string newPurchaseOrderNumber =
(string)rec1.GetValue(rec1.GetOrdinal("PurchaseOrderNumber"));
// Get the modified properties.
IEnumerable<string> modifiedFields = stateEntry.GetModifiedProperties();
foreach (string s in modifiedFields)
Console.WriteLine("Modified field name: 0\n Old Value: 1\n New Value: 2",
s, oldPurchaseOrderNumber, newPurchaseOrderNumber);
// Get the Entity that is associated with this ObjectStateEntry.
SalesOrderHeader associatedEnity = (SalesOrderHeader)stateEntry.Entity;
Console.WriteLine("Associated Enity's ID: 0", associatedEnity.SalesOrderID);
【讨论】:
使用向导从 db 生成模型,典型代码 repo.entity.value = newvalue 进行更改 有趣,它是否可以扩展到多行,例如“表”是否绑定到网格并且用户对一行进行了更改,但我事先不知道是哪一个!!还是我需要为列表中的每条记录获取并存储 ObjectStateEntry(很容易有 > 10000 个条目) 您只能查询ObjectStateManager
进行更改
另一个故事是,如果在内存中加载了 10k 个实体,您可以对 Entity Framework 使用更复杂的方法,即在 OnChange 处理程序中将实体加载为分离的,将实体附加到上下文中,这将在上下文的ObjectStateManager
并且不要为整个 10k 集合的状态条目浪费资源。
还考虑研究可用于实体框架的扩展,例如在其之上构建的存储库,因为默认生成的上下文实现了工作单元模式并暗示相应地使用【参考方案2】:
使用数据库结构本身来执行此操作通常是一种很好的做法。 这只是您现在的另一种方法。
您可以在名为 ModifiedOn
的表中创建一个 datetime
类型的新字段,并在每次更新数据库中的行时更新它。
然后,当您希望在特定时间后更改行时,您只需使用:
where ModifiedOn > dateTime
这只是关于如何从不同角度解决问题的另一个建议。
【讨论】:
一般来说你甚至不需要手动更新字段,有专门的字段类型——时间戳。这种方法完全有道理,但它只允许您获得更改的时间。您仍然需要手动获取实际更改,您可以做的只是将原始记录与新记录一起保存或使用更复杂的方法,如查询日志(在 SQL Server 中)。另一方面,EntityFramework 在执行数据库更新之前已经保存了这些信息,因此使用这些现有数据是非常明显的决定 @vittore - 是的。我完全同意你的看法。我只是想指出,对于这个特殊问题,还有其他方法。以上是关于如何在 EF 中获取实体更改增量?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 .SaveChanges() 期间首先使用 EF 代码记录所有实体更改?
如何在使用EF代码的.SaveChanges()期间记录所有实体更改?