2013-02-06 110 views
1

將項目從EntityObject生成器切換到DbContext後,我遇到了一個問題,在新對象上使用了一些導航屬性。我花了大量的時間來研究這個問題,並且我沒有接近一個理想的解決方案。EF 4.4中的DbContext和導航屬性

首先,生成的類定義:

public partial class Category 
{ 
    public Category() 
    { 
     this.Limits = new HashSet<Limit>(); 
    } 

    public int CategoryId {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<Limit> Limits { internal get; set; } 
} 

public partial class Limit 
{ 
    public int CategoryId {get; set;} 
    public string Description {get; set;} 
    internal virtual Category Category { get; set; } 
} 

我使用下面的代碼集成測試期間創建的測試數據:

using (GFCAMDataContext db = new GFCAMDataContext()) 
{ 
    limit = new Limit() 
    { 
     CategoryId = testData.CategoryId, 
     Description = "SignerController.Update" 
    }; 

    db.Limits.Add(limit); 
    db.SaveChanges(); 
} 

沒有任何其他的變化,在Limit.Category財產我新創建的Limit對象不返回任何東西。但是,如果在調用SaveChanges之前從DbContext查詢所需的類別,則新限制的導航屬性開始返回關聯的類別。使用ObjectContext,Category屬性在沒有任何干預的情況下進行更新。

我想與ObjectContext具有相同的行爲,但我似乎無法找到實現此目標的方法。我見過幾種建議的解決方案:

  • 使導航屬性公開。這具有相同的行爲,並且不可取,因爲公共導航屬性可能會在序列化期間導致問題,並且在我的業務層之外不需要。

  • 使所有屬性公開爲虛擬並使用DbSet.Create確保代理創建。這導致了相同的行爲,並不一定需要,因爲我有代碼動態創建實例(即我在創建實體實例時沒有訪問DbSet)。

有沒有人有任何解決這個問題的建議?

+0

這似乎是懶惰加載不踢英寸什麼是Limit類的CategoryId?它是主鍵還是外鍵還是兩者?如何爲此類配置主鍵 - EF將無法使用約定來發現此類的鍵,並且您應該會收到一個異常,表明實體類型沒有鍵屬性。 – Pawel

+0

只是要說得很清楚:你說SaveChanges()調用Category屬性後沒有填充? –

回答

0

一個解決辦法是顯式地加載嵌套實體:

db.SaveChanges(); 
db.Entry(person).Reference(z => z.Category).Load(); 

另一種選擇,當代理啓用,的確叫DbSet.Create<T>()。如果您在創建實體時無法訪問DbSet實例,則可能希望在存儲庫接口中公開一個允許實現的方法。例如:

public interface IRepository<T> 
{ 
    T Add(T entity); 

    T GetById(...); 

    void SaveChanges(); 

    ... 

    T CreateInstance(); // Concrete implementation have access to DbSet and uses DbSet.Create<T>() 
}