我有一个带有一些依赖BO的BO(通过导航属性),它代表数据库中的几个链接表。例如,Person主表和Address,Education表,通过Person_Address,Person_Education表,1对多链接。
我们需要跟踪特定人员在“人员”,“地址”,“教育”表格中发生的更改。这三个表中的任何更新都应将Person.LastRecordUpdate日期更新为当前日期。我没有看到跟踪Person表本身的任何问题。但是,我们需要跟踪其他两个表(Address,Education)中的更改,这两个表具有AddressId,EducationId PK和没有PersonId(因为它们通过中间表与主表链接)。并且保存在Address中,教育发生在另一个dbcontext实体中,即人员的节省。我该如何解决这个问题?
答案 0 :(得分:1)
我从包含public virtual DateTime? LastModified
属性的ModelBase派生所有业务对象。它还实现了接口
public interface IHasLastModified
{
DateTime? LastModified { get; set; }
}
然后我覆盖SaveChanges()
中的DbContext
以查找实现IHasLastModified
的任何添加或修改内容,并设置修改后的时间戳。
另外,关于在调试器中显示DbEntityValidationException
详细信息,EF很奇怪。出于这个原因,在这段代码中我也处理了这个问题
通过构建在调试器中直接查看的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不支持完整对象图合并,并且可以让您自行管理。