2015-10-07 87 views
1

我有一些BO与一些依赖BO(通过导航属性),它们代表数据库中的多个链接表。例如,通过Person_Address,Person_Education表连接的Person主表和Address,Education表,一对多。检测对复杂对象的更改

我们需要跟踪在特定人员的人员,地址,教育表格上发生的变化。这三个表中的任何更新都应该将Person.LastRecordUpdate日期更新为当前日期。我没有看到任何问题来跟踪Person表本身。但是,我们需要跟踪其他两个表(地址,教育)中的变化,这些表具有AddressId,EducationId PK和没有PersonId(因为它们通过中间表与主表链接)。并且保存在Address中,教育发生在另一个dbcontext实体中,即人员保存。我该如何解决这个问题?

+0

为什么你在1到多表中使用摆台?你的意思是多对多的关系(许多用户可以有相同的教育或地址)? –

回答

1

我从包含public virtual DateTime? LastModified属性的ModelBase派生出所有业务对象。它还实现了接口

public interface IHasLastModified 
{ 
    DateTime? LastModified { get; set; } 
} 

然后我重写我的DbContextSaveChanges()寻找被添加或修改实现IHasLastModified什么,并设置修改时间戳。

在附注中,EF在调试器中显示DbEntityValidationException的详细信息很古怪。出于这个原因,在这段代码中,我还通过构建errorList来处理 异常,这很容易在调试器中查看,并且还记录了详细信息。在我的代码中,logger是一个NLog记录器。你可以用 使用任何其他记录器,或删除该行。

public override int SaveChanges() 
{ 
    try 
    { 
     DateTime now = DateTime.UtcNow; 
     foreach (ObjectStateEntry entry in (this as IObjectContextAdapter).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)) 
     { 
      //logger.Info("Setting LastModified on " + entry.Entity.GetType().FullName); 
      if (!entry.IsRelationship) 
      { 
       IHasLastModified lastModified = entry.Entity as IHasLastModified; 
       if (lastModified != null) 
        lastModified.LastModified = now; 
      } 
     } 

     return base.SaveChanges(); 
    } 
    catch (DbEntityValidationException valEx) 
    { 
     List<string> errorList = new List<string>(); 

     foreach (var error in valEx.EntityValidationErrors) 
     { 
      foreach (var entry in error.ValidationErrors) 
      { 
       errorList.Add(entry.PropertyName + ": " + entry.ErrorMessage); 
      } 

      logger.Error(string.Join(";", errorList)); 
     } 
     throw; 
    } 
} 

于地址保存,教育发生在其他的DbContext实体,从而节省的人。

合并跨多个DbContext实例的更改非常非常棘手。 EF不提供对所有情况的全面支持。

我强烈建议避免这种情况。传递一个DbContext的单个实例,而不是尝试合并来自两个DbContext图像的更改。

如果您确实想要尝试管理两个上下文实例中发生的更改,请查看this writeup。请注意结论性意见

截至今天,EF不支持全对象图合并,并让您自己管理。

+0

我通常重写'SaveChanges',但是使用'LastModified'的那个接口,这是个好主意。我将在我的下一个项目中实施它! –

+0

Eric,在这种情况下,您的解决方案如何提供帮助:假设,我有以下数据库内容:Person.LastRecordUpdate;我在Address表中还有一个地址记录,它通过Person_Address表与Person表链接 - 正确的,多对多 - 。我修改该地址记录中的邮政编码,那么我应该如何跟踪它,以便我能够自动更新Person.LastRecordUpdate值? –

+0

@ TakhirMamirov:每个保存的实体都会自动应用时间戳。将我的'LastModified'改为你的'LastRecordUpdate'。如果是父母或小孩,无关紧要。 –