2011-04-26 96 views
2

我想向我的實體添加一些自定義邏輯。每個實體都有一個CreatedBy & LastUpdatedBy屬性。實體框架4自定義邏輯保存更改

我已經添加了下面的代碼工作正常,如果我添加例如一個人和他們的地址在旅途中。

但是,如果我添加Person並調用context.SaveChanges(),然後添加他們的地址並調用context.SaveChanges()。該代碼執行但「entry」的值爲空,因此CreatedBy & LastUpdatedBy未填充。

CustomRepository.CurrentUser只是獲取用戶名。

ObjectSet = context.CreateObjectSet<TEntity>(); 

BusinessEntities.Person person = new BusinessEntities.Person() 
{ 
    TitleRef = 123, 
    FirstName = "FirstName", 
    Surname = "Surname", 
    PhoneNumber = "PhoneNumber", 
    MobileNumber = "MobileNumber", 
    EmailAddress = "EmailAddress", 
}; 


ObjectSet.AddObject(entity); 

Context.SaveChanges(); 

PersonAddress personAddress = new BusinessEntities.PersonAddress 
{ 
    StartDate = DateTime.Now, 
    EndDate = DateTime.Now, 
    OtherResidents = "OtherResidents", 
    CurrentAddress = true, 
    Address = new Address 
    { 
     Address1 = "Address1", 
     Address2 = "Address2", 
     Address3 = "Address3" 
    } 
}; 

Context.SaveChanges(); 


public override int SaveChanges(SaveOptions options) 
{ 
    foreach (ObjectStateEntry entry in 
     ObjectStateManager.GetObjectStateEntries(
     EntityState.Added | EntityState.Modified)) 
    { 
     System.Collections.ObjectModel.ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues 
           .DataRecordInfo.FieldMetadata; 

     FieldMetadata createdField = fieldsMetaData 
     .Where(f => f.FieldType.Name == "CreatedBy").FirstOrDefault(); 

     FieldMetadata modifiedField = fieldsMetaData 
     .Where(f => f.FieldType.Name == "LastUpdatedBy").FirstOrDefault(); 

     if (modifiedField.FieldType != null) 
     { 
      string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name; 
      if (fieldTypeName == PrimitiveTypeKind.String.ToString()) 
      { 
       if (entry.CurrentValues[createdField.Ordinal].ToString() == null || 
        entry.CurrentValues[createdField.Ordinal].ToString() == String.Empty) 
       { 
        entry.CurrentValues.SetString(createdField.Ordinal, CustomRepository.CurrentUser); 
       } 

       entry.CurrentValues.SetString(modifiedField.Ordinal, CustomRepository.CurrentUser); 
      } 
     } 
    } 
    return base.SaveChanges(options); 
} 

------------------------原始方法----------------- ------------

private void Initialize() 
{ 
    // Creating proxies requires the use of the ProxyDataContractResolver and 
    // may allow lazy loading which can expand the loaded graph during serialization. 
    ContextOptions.ProxyCreationEnabled = false; 
    ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized); 

    OnContextCreated(); 
} 

private void OnContextCreated() 
{  
    this.SavingChanges += Context_SavingChanges; 
} 

private void Context_SavingChanges(object sender, EventArgs e) 
{ 
    try 
    { 
     IEnumerable<ObjectStateEntry> objectStateEntries = 
     from ose 
     in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added 
                  | EntityState.Modified) 
     where ose.Entity != null 
     select ose; 

     foreach (ObjectStateEntry entry in objectStateEntries) 
     { 
      System.Collections.ObjectModel.ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues 
       .DataRecordInfo.FieldMetadata; 

      FieldMetadata createdField = fieldsMetaData 
      .Where(f => f.FieldType.Name == "CreatedBy").FirstOrDefault(); 

      FieldMetadata modifiedField = fieldsMetaData 
      .Where(f => f.FieldType.Name == "LastUpdatedBy").FirstOrDefault(); 

      if (modifiedField.FieldType != null) 
      { 
       string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name; 
       if (fieldTypeName == PrimitiveTypeKind.String.ToString()) 
       { 
        if (entry.CurrentValues[createdField.Ordinal].ToString() == null || 
         entry.CurrentValues[createdField.Ordinal].ToString() == String.Empty) 
        { 
         entry.CurrentValues.SetString(createdField.Ordinal, CustomRepository.CurrentUser); 
        } 

        entry.CurrentValues.SetString(modifiedField.Ordinal, CustomRepository.CurrentUser); 
       } 
      } 
     } 
    } 
} 
+1

您還應該顯示您的「人員」和「地址」實體,以及如何添加它們。 – 2011-04-26 17:51:17

回答

0

您應該處理SavingChanges事件,而不是覆蓋該方法。

此外,爲什麼不讓你的實體從基類繼承或實現一個接口,而不是使用反射?如果您首先使用模型/數據庫,您可以在T4模板中執行此操作,或者如果您先使用代碼,則可以直接在T4模板中執行此操作,從長遠來看,您可以獲得比反射更好的結果。您也可以編寫通用篩選器來查找在日期範圍內修改的實體,因爲您可以針對您的界面進行工作。

我使用ObjectStateManager.GetObjectStateEntries(EntityState.Modified).OfType(Of T)(或任何我想要的狀態,無論我想要哪種實體類型) - 它使我可以針對實際實體而不是ObjectStateEntry工作。

+0

我使用T4與POCO Self Tracking並將我的代碼分離到不同的項目中。我創建了一個實現通用功能的BaseRepository類。我已經實現了this.SavingChanges + = Context_SavingChanges;並使用ObjectStateManager,但同樣存在問題。剛剛在上面編輯。 – markpcasey 2011-04-27 10:32:44

+0

嗨,我仍然堅持在這個問題任何幫助woyuld是偉大的。我的實體像這樣繼承Person:IObjectWithChangeTracker,INotifyPropertyChanged使用T4 temlpates。 – markpcasey 2011-05-05 12:34:53

2

我終於得到了答案。我需要在Save()之前調用Context.DetectChanges(),否則不會檢測到更改。