2015-10-07 83 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'。如果是父母或小孩,無關緊要。 –