簡體   English   中英

實體框架代碼首先審核多對多和一對多的問題

[英]Entity Framework Code First Auditing many-to-many and one-to-many issues

我一直試圖創建一個審計跟蹤,試圖通過TrackChanges嘗試許多不同的方法,覆蓋SaveChanges()並簡單地抓取實體並使用DbEntityEntry.OriginalValues獲取原始值。原始值所有這些方法最終歸結為相同問題。 當我將另一個模型作為ICollection引用時,它不會在實體中記錄此模型。 作為此問題的一個非常基本的解釋,請參閱以下代碼:

public void Update(Project project)
{
    _ctx.OriginalValues(project);
    _ctx.Projects.Attach(project);
    _ctx.Entry(project).State = EntityState.Modified;
    _ctx.SaveChanges(project);
}

上面的.OriginalValues在引發保存更改之前將實體傳遞給此方法,並且我能夠在用戶更改之前讀取實體中的值。 OriginalValues方法如下所示:

public void OriginalValues(object entity)
{
    var entry = this.Entry(entity);               
    System.Reflection.PropertyInfo[] names = entity.GetType().GetProperties();            

    foreach (var property in names)
    {               
        var n = entry.OriginalValues[property.Name];                   
    }
}

我所理解的上述方法並不是非常優雅或最佳實踐,但它是從我的實體中讀取原始值的長期嘗試的最新嘗試。

當此代碼運行時, property.Name將獲得一個名為“Teams”的名稱,該名稱在Project模型中被引用:

public class Project
{       
    public int Id { get; set; } // PK
    public string Name { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int MarketId { get; set; } // FK
    [ForeignKey("MarketId")]
    public Market Market { get; set; } // FK Nav   
    public ICollection<Team> Teams { get; set; } // Many to Many Nav 
}

拋出一個錯誤,告訴我它沒有映射到Project,即使我已經使用流暢的API和數據注釋來嘗試獲取此映射。

這是一個例子我在其他模型中遇到相同的情況,但有很多關系。

我是一名研究生開發人員,因此沒有大量的.net信息我希望有人可以提供任何建議或支持,如果可能的話!

謝謝

編輯:顯示錯誤消息:

“團隊”屬性不存在或未針對“項目”類型進行映射。

描述:執行當前Web請求期間發生未處理的異常。 請查看堆棧跟蹤以獲取有關錯誤及其源自代碼的位置的更多信息。

異常詳細信息:System.ArgumentException:'Teams'屬性不存在或未映射到'Project'類型。

來源錯誤:

Line 78:             foreach (var property in names)
Line 79:             {               
Line 80:                 var n = entry.OriginalValues[property.Name];                   
Line 81:                 
Line 82:             }

出現此錯誤是因為EF將每個條目的值保存在其自己的對象中,因此導航屬性的值將保存在其條目中,因此它們不在當前對象的OriginalValues中。 您可以訪問導航屬性,如下所示:

foreach (var property in names)
{
    var m = entry.Member(property.Name);
    if (m is DbPropertyEntry)//simple property
    {
         var p = entry.Property(property.Name);
    }
    if (m is DbReferenceEntry)//navigation to single object
    {
         var r = entry.Reference(property.Name);
    }
    if (m is DbCollectionEntry)//navigation to collection
    {
         var c = entry.Collection(property.Name);
    }
}

然后,您可以將每個導航對象視為新對象並檢索它們的原始值。

建議: EF內部有一個跟蹤系統,可跟蹤對象圖的所有更改,您可以查詢此跟蹤系統並記錄更改,如下所示。 無需跟蹤引用,因為如果它們發生了更改,則EF會檢測它。

public void OriginalValues(object entity)
{
    ChangeTracker.DetectChanges();
    var changed = ChangeTracker.Entries()
            .Where(x=>x.State != EntityState.Unchanged).ToList();
    foreach (var entry in changed)
    {
        switch (entry.State)
        {
            case EntityState.Added:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "created:");
                foreach(var name in entry.CurrentValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
                }
            break;
            case EntityState.Deleted:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "deleted:");
                foreach(var name in entry.OriginalValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
                }
            break;
            case EntityState.Modified:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "updated:");
                Debug.WriteLine("current values:");
                foreach(var name in entry.CurrentValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
                }
                Debug.WriteLine("original values:");
                foreach(var name in entry.OriginalValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
                }
            break;
         }
     }
 }

注意:確保在刪除對象時將狀態設置為“ Deleted刪除”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM