我發現了與使用.Include
等進行加載有關的各種問題,但它好像是SQL形狀查詢到一個巨大的聯接,這意味着如果我得到客戶信息以及客戶擁有1000個項目,我做實體框架 - 爲集合中的成員加載特定導航屬性
context.Customers.Include(c=> c.Inventory).Where(c=>c.ID == id);
//side note, WHY can't I use .Find() after Include?
我會得到1000行與項目信息,而不是1條的客戶記錄,並在多臺套1000項一起重複相同的客戶信息。這看起來效率很低,會導致一些非常慢的查詢。
所以,如果我有一組客戶:
//get all customers in TX
var texasCustomers = context.Customers.Where(c=> c.State == "TX");
我要循環他們出口到XLSX:
foreach (var c in texasCustomers) {
//compile row per item SKU
foreach(var sku in c.Inventory.GroupBy(i=>i.SKU)) {
xlsx.SetCellValue(row, col, c.Name);
//output more customer info here
xlsx.SetCellValue(row, col, sku.Key);
xlsx.SetCellValue(row, col, sku.Sum(i=>i.Quantity));
}
}
這生成一個查詢到「清單」表PER客戶。這是一個快速查詢,但是當您執行1000次SAME查詢時,它會變得非常慢。
這樣所以我所做的事情:
//get customer key
var customerids = texasCustomers.Select(c=> c.ID).ToArray();
var inventories = context.Inventories.Where(i=> customerids.Contains(i.CustomerID)).ToList();
...現在我出口環看起來更像這個...內環從第一個例子中的導航性能運行變爲同對清單對象的預建列表-Memory LINQ過濾器:
foreach (var c in texasCustomers) {
//compile row per item SKU
foreach(var sku in inventories.Where(i=> i.CustomerID == c.ID)) {
xlsx.SetCellValue(row, col, c.Name);
//output more customer info and then the sku info
xlsx.SetCellValue(row, col, sku.Key);
xlsx.SetCellValue(row, col, sku.Sum(i=>i.Quantity));
}
}
這成功地得到周圍發出「每循環查詢」,但有明顯的缺點......,只是覺得不妥。
那麼,我錯過了什麼?那是哪裏讓我做類似的祕密EF特點:
texasCustomers.LoadAll(c=> c.Inventories);
爲「填充」所有集合成員的導航性能的一個去了?還是我從錯誤的角度來處理問題?
有沒有一種方法來構造查詢來獲得EF來生成不會變成單個巨型非規格化表的SQL?
啊,這感覺好多了。去給這個鏡頭。謝謝。 – BLSully
優秀信息!這讓我有90%的途徑。似乎是我還不明白的一些方面(例如:不是從'.Find()'工作,但如果我給它一個未處理的'.AsQueryable()',它可以工作嗎?不是)但是,我的EF數據庫日誌從4MEGAbytes下降到7KB(4批量查詢與〜1000x3碎片查詢) – BLSully
事實上,它只適用於'IQueryable's。對於Find來說,幾乎沒有任何與加載有關的數據方法不能直接與它一起工作,所以只要忘記它 - 使用簡單的Where或FirstOrDefault等。儘管對於單個實體,您可以以任何方式獲得它,包括找到',然後使用導航集合屬性的[顯式加載](https://msdn.microsoft.com/en-us/library/jj574232(v = vs.113).aspx#Anchor_2)。順便說一句,在我的答案中使用的技術是**的應用過濾器,當明確加載鏈接中的相關實體**部分。 –