我正在使用Entity Framework處理更大的系統。就我個人而言,我喜歡編寫LINQ/ESQL查詢的基於方法的語法。如何在Entity SQL中使用基於方法的語法編寫正確連接的查詢?
但我cannnot弄清楚,如何加入下面的查詢可以正確編寫。
想,我有以下實體類和的DbContext庫:
public class A
{
[Key]
public int ID{get;set;}
public virtual ICollection<B> BCollection { get; set; }
}
public class B
{
[Key]
public int ID { get; set; }
public virtual A A { get; set; }
public virtual ICollection<C> CCollection { get; set; }
public virtual ICollection<D> DCollection { get; set; }
}
public class C
{
[Key]
public int ID { get; set; }
public virtual B B { get; set; }
}
public class D
{
[Key]
public int ID { get; set; }
public virtual B B { get; set; }
}
public class Entities : DbContext
{
public DbSet<A> SetA { get; set; }
public DbSet<B> SetB { get; set; }
public DbSet<C> SetC { get; set; }
public DbSet<D> SetD { get; set; }
}
現在我想「整」樹:A類的所有項目,與它們連接的B類項目,其中每個B類項目配備了C類的項目和D.
我能做到這一點與此查詢:
var x = db.SetA
.Include(a => a.BCollection.Select(b => b.CCollection))
.Include(a => a.BCollection.Select(b => b.DCollection))
.ToList();
但我認爲這是可以做到更容易,對不對?
請注意:我想加載整個樹,因爲我不想使用延遲加載。
編輯:
這不是關於一個單一的問題一個問題,我的問題是更多的辦法。當我寫我的查詢,如上面所示,EF產生一個巨大的查詢的地獄:
SELECT [Project3].[ID] AS [ID],
[Project3].[C9] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
[Project3].[C4] AS [C4],
[Project3].[C1] AS [C5],
[Project3].[C5] AS [C6],
[Project3].[C6] AS [C7],
[Project3].[C7] AS [C8],
[Project3].[C8] AS [C9]
FROM (SELECT [Extent1].[ID] AS [ID],
[UnionAll1].[C1] AS [C1],
[UnionAll1].[ID] AS [C2],
[UnionAll1].[ID1] AS [C3],
[UnionAll1].[A_ID] AS [C4],
[UnionAll1].[ID2] AS [C5],
[UnionAll1].[B_ID] AS [C6],
[UnionAll1].[C2] AS [C7],
[UnionAll1].[C3] AS [C8],
CASE
WHEN ([UnionAll1].[ID] IS NULL) THEN CAST(NULL AS int)
ELSE 1
END AS [C9]
FROM [dbo].[A] AS [Extent1]
OUTER APPLY (SELECT CASE
WHEN ([Extent3].[ID] IS NULL) THEN CAST(NULL AS int)
ELSE 1
END AS [C1],
[Extent2].[ID] AS [ID],
[Extent2].[ID] AS [ID1],
[Extent2].[A_ID] AS [A_ID],
[Extent3].[ID] AS [ID2],
[Extent3].[B_ID] AS [B_ID],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3]
FROM [dbo].[B] AS [Extent2]
LEFT OUTER JOIN [dbo].[C] AS [Extent3]
ON [Extent2].[ID] = [Extent3].[B_ID]
WHERE [Extent1].[ID] = [Extent2].[A_ID]
UNION ALL
SELECT 2 AS [C1],
[Extent4].[ID] AS [ID],
[Extent4].[ID] AS [ID1],
[Extent4].[A_ID] AS [A_ID],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
[Extent5].[ID] AS [ID2],
[Extent5].[B_ID] AS [B_ID]
FROM [dbo].[B] AS [Extent4]
INNER JOIN [dbo].[D] AS [Extent5]
ON [Extent4].[ID] = [Extent5].[B_ID]
WHERE [Extent1].[ID] = [Extent4].[A_ID]) AS [UnionAll1]) AS [Project3]
ORDER BY [Project3].[ID] ASC,
[Project3].[C9] ASC,
[Project3].[C3] ASC,
[Project3].[C1] ASC
但我居然會寫我自己是這樣的:
SELECT *
FROM D RIGHT OUTER JOIN
B ON D.B_ID = B.ID LEFT OUTER JOIN
C ON B.ID = C.B_ID RIGHT OUTER JOIN
A ON B.A_ID = A.ID
我希望這有助於澄清我題。重點是:如何讓Entity Framework生成更高效的查詢?
嗯,你的樹,在不改變惰性加載的配置,您的解決方案是好的(但它的會是一個「重」SQL請求...) –
當然,我不想使用懶加載。比10.000個輕量級請求更重要的一個請求。但是你是對的,結果是一個包含三個子查詢和很多UNION的大型查詢。那我怎麼能改進呢? – ckonig
你可以嘗試使用一個匿名對象('db.SetA.Select(seta => new {a = seta,bcoll = seta.BCollection'等),並測試它是否更快)如果perf是FINAL問題..使用「hard written」sql請求 –