使用實體框架我只想包含第一個子對象而不是子的子(子的子)
使用實體框架我只想包含第一級子對象而不是子對象
我有這兩個類:
public class BusinessesTBL { public string ID { get; set; } public string FirstName { get; set; } public string lastName { get; set; } public ICollection<OffersTBL> OffersTBLs { get; set; } } public class OffersTBL { public int ID { get; set; } public string Name { get; set; } public int CatId { get; set; } public string BusinessesTBLID { get; set; } public virtual BusinessesTBL BusinessesTBLs { get; set; } }當我嘗試根據 CatId 欄位提供所有優惠時,我還需要返回 BusinessesTBLs,但該方法還會根據每個 BusinessesTBL obj 再次返回優惠,我的程式碼是:
public IQueryable<OffersTBL> GetOffersTBLsCat(int id) { db.OffersTBLs.Include(s => s.BusinessesTBLs); }您可以在以下位置看到錯誤的結果: http: //mycustom.azurewebsites.net/api/OffersApi/GetOffersTBLsCat/4
如您所見,它返回每個業務對像下的所有報價,而每個報價下的業務對象,我只想返回帶有其業務對象的報價,而不返回業務對像下的報價。
有人可以幫忙嗎?
一個downvote讓這個答案重新引起了我的注意(謝謝)。我現在看到其中很大一部分是胡說八道。
果然,死循環的原因是關係修復。但是你不能阻止 EF 這樣做。即使在使用時
AsNoTracking,EF 也會在一個查詢中具體化的對像中執行關係修復。因此,您的查詢Include將導致完全填充的導航屬性OffersTBLs和BusinessesTBLs.消息很簡單:如果您不希望結果中出現這些引用循環,則必須投影到視圖模型或 DTO 類,如其他答案之一。在我看來,在進行序列化時,另一種不太吸引人的方法是將序列化程序配置為忽略引用循環。另一個不太吸引人的替代方法是單獨獲取對象
AsNoTracking並自己有選擇地填充導航屬性。原答案:
發生這種情況是因為 Entity Framework 執行關係修復,這是在上下文中存在屬於那裡的對象時自動填充導航屬性的過程。因此,使用循環引用,即使禁用延遲載入,您也可以無休止地向下鑽取導航屬性。Json 序列化程序正是這樣做的(但顯然它被指示處理循環引用,因此它不會陷入無限循環)。
訣竅是防止關係修復發生。關係修復依賴於上下文
ChangeTracker,它記憶體對像以跟踪它們的更改和關聯。但是,如果沒有什麼可跟踪的,就沒有什麼可修復的。您可以通過呼叫停止跟踪AsNoTracking():db.OffersTBLs.Include(s => s.BusinessesTBLs) .AsNoTracking()如果除此之外您還禁用了上下文的延遲載入(通過設置
contextConfiguration.LazyLoadingEnabled = false),您將看到僅OffersTBL.BusinessesTBLs填充在 Json 字元串中並且BusinessesTBL.OffersTBLs是空數組。一個好處是
AsNoTracking()提高了性能,因為更改跟踪器並不忙於跟踪 EF 實現的所有對象。事實上,您應該始終在斷開連接的環境中使用它。