2015-04-22 86 views
2

我有以下型號:EF加載虛擬導航屬性,而無需訪問

public class Category 
{ 
    public virtual ICollection<Product> Products{get;set;} 
    public Product() 
    { 
     Products = new HashSet<Product>(); 
    } 
} 

public class Product 
{ 
    public Guid CategoryId{get;set;} 
    public virtual Category {get;set;} 
} 

現在如果我執行以下語句:

var list = await UoW.Categories.Query.Where(x=>x.Name.Contains("Mob")).ToListAsync(); 

,並返回listJSON從MVC控制器動作。它拋出以下異常:

A circular reference was detected while serializing an object of type 
'System.Data.Entity.DynamicProxies.Category_7C2191CFExxxxxxx'. 

它發生,因爲Products集合不爲空,反過來每個Product包含Category

虛擬財產自動上傳的原因是什麼?

編輯: - 原來Json序列化程序正在訪問的屬性,並導致EF加載它們。按照haim770的建議關閉LazyLoading

+0

爲什麼不在'Product'類的'Category'屬性中應用''[NonSerialized,XmlIgnore]'並消除循環引用? –

+0

可能重複的http://stackoverflow.com/questions/2967214/disable-lazy-loading-by-default-in-entity-framework-4 – Anil

回答

1

原因是實體框架代理正在攔截對您的Products屬性的訪問並自動填充它。

你可以明確地把延遲加載過,但:

context.Configuration.LazyLoadingEnabled = false; 

您還可以項目Category列表成爲一個新列表,只填充所需的性能。例如:

var list = await UoW.Categories.Query.Where(x=>x.Name.Contains("Mob")) 
            .Select(x => new Category { 
              Id = x.Id, 
              Name = x.Name 
            }).ToListAsync(); 
+0

是的我可以投影到一個新的對象,並將延遲加載爲false。但是我的好奇心是這是因爲序列化訪問導致EF加載虛擬成員的屬性? – TheVillageIdiot

+0

是的。串行器通過嘗試序列化來訪問該屬性。 – haim770

+0

是的,在最後序列化導致問題。禁用延遲加載。 – TheVillageIdiot

0

WCF嘗試遍歷對象並序列化整個對象圖。如果您啓用了延遲加載(因爲它是默認設置),它將會停留在此循環引用中。

一個選項是關閉延遲加載,如haim770所示。另一種方法是返回Data Transfer Objects,而不是直接返回EF對象。

也可以用循環引用完整地返回對象圖。但是,您需要創建一個自定義DataContractSerializerOperationBehavior和一個自定義屬性來應用該行爲。 Sowmy Srinivasan的blog post有完整的細節。