我正在编写一个软件,它从各种来源接收人员信息,所有这些数据都存储到数据库中。棘手的部分是当这些信息被合并到主记录时。这种组合被实现为不同类型步骤的管道,这些步骤根据从源接收的信息更新主记录。所有步骤都实现了一个IPersonUpdatingStep
具有Update(Person person)
方法的通用接口。
我想记录哪些更新的字段,特别是哪个步骤负责更改。不同的步骤可能会更新同一个字段,我只对主记录通过整个管道后出现的最后一次更改感兴趣。
我的第一个直觉是在对象进入一个步骤时对其进行深拷贝,在它返回后进行另一个深拷贝,并根据这些副本进行差异。然而,深度复制使用 Entity Framework 的 Database First 工具生成的类的对象似乎相当困难。如果浅拷贝就足够了,那将非常容易,但我需要知道存储在集合中的任何相关实体是否已更改。
一个建议的深度复制简单解决方案是序列化和反序列化对象,但由于模型是基于数据库自动生成的,我无法添加这些 Serializable 属性。
问题更加困难,因为该对象具有相关实体和相关实体的集合,因此我需要知道某些步骤是否更改了这些相关集合实体的某些属性。
我不想更改管道步骤,以便每个步骤都包含如下代码:
if (targetPerson.FirstName != sourcePerson.FirstName)
{
targetPerson.FirstName = sourcePerson.FirstName;
changes.Add("FirstName", "Name of the step responsible for the change");
}
但是还有另一种可读且可靠的选择吗?我知道在将对象保存到数据库时如何使用 Entity Framework 编写审计跟踪,但在那个阶段我只能记录哪些属性已更改,而我更感兴趣的是哪个管道步骤负责更改场地。
我觉得我没有做任何开创性的事情,以至于其他人不会遇到同样的问题。
更新: haim770 关于 ChangeTracker API 的建议很好。我设法获取有关更改的基本属性的信息,但是如何获取有关更改的关系的信息?例如,我的Person
对象与对象具有一对多的关系Address
。我想获得的信息不仅是关于哪个Address
对象被更新,更具体地说,是那个Address
对象的哪个属性被改变了。
DbEntityEntry entry = _source.Context.Entry(person);
foreach (var property in entry.Entity.GetType().GetProperties())
{
DbMemberEntry propertyEntry = entry.Member(property.Name);
if (propertyEntry is DbPropertyEntry)
{
var foo = propertyEntry as DbPropertyEntry;
if (foo.IsModified)
{
changes.Add(step.GetType().Name + ": " + property.Name);
}
}
// How to handle relationships?
}