我正在编写一个从各种来源接收人员信息的软件,所有这些数据都存储在数据库中。棘手的部分是将这些信息合并到主记录中。这种组合被实现为不同类型步骤的流水线,其根据从源接收的信息更新主记录。所有步骤都实现了一个具有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?
}