我有一個數據庫結構如下的EntityFramework生成TSQL差(linqpad產生好得多)
家庭(1) - - - - (*)FamilyPersons - - - - (1)人(1) ------()費用(1)-----(0..1)雜貨詳情
讓我解釋一下關係,家庭可以有一個或多個人,我們有一個映射表家庭人與人之間的家庭人。現在每個人都可以輸入他的費用,進入費用表。費用表有一列ExpenseType(雜貨,娛樂等) 和每個這些費用的細節進入他們自己的表,所以我們有一個GroceriesDetails表(同樣我們有其他表),所以我們有1到0..1的關係費用和雜貨之間。
現在我正在寫一個查詢,以獲得完整的GroceriesDetails爲家庭
GroceriesDetails.Where (g => g.Expenses.Person.FamilyPersons.Any(fp =>
fp.FamilyId == 1) && g.Expenses.ExpenseType == "GC")
對於這個由EF生成的SQL是
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Amount] AS [Amount]
FROM [dbo].[GroceriesDetails] AS [Extent1]
INNER JOIN (SELECT [Extent3].[Id] AS [Id1]
FROM [dbo].[Expenses] AS [Extent2]
INNER JOIN [dbo].[GroceriesDetails] AS [Extent3] ON [Extent2].[Id] = [Extent3].[Id]
WHERE N'GC' = [Extent2].[ExpenseType]) AS [Filter1] ON [Extent1].[Id] = [Filter1].[Id1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Expenses] AS [Extent4]
INNER JOIN [dbo].[GroceriesDetails] AS [Extent5] ON [Extent4].[Id] = [Extent5].[Id]
INNER JOIN [dbo].[FamilyPerson] AS [Extent6] ON [Extent4].[PersonId] = [Extent6].[PersonId]
WHERE ([Extent1].[Id] = [Extent5].[Id]) AND (1 = [Extent6].[FamilyId])
)
在此查詢有一個全表費用之間的連接和導致性能問題的GroceriesDetails表。
而Linqpad產生一個更好的SQL
SELECT [t0].[Id], [t0].[Amount]
FROM [GroceriesDetails] AS [t0]
INNER JOIN [Expenses] AS [t1] ON [t1].[Id] = [t0].[Id]
WHERE (EXISTS(
SELECT NULL AS [EMPTY]
FROM [Expenses] AS [t2]
INNER JOIN [Person] AS [t3] ON [t3].[Id] = [t2].[PersonId]
CROSS JOIN [FamilyPerson] AS [t4]
WHERE ([t4].[FamilyId] = @p0) AND ([t2].[Id] = [t0].[Id]) AND ([t4].[PersonId] =
[t3].[Id])
)) AND ([t1].[ExpenseType] = @p1)
請注意,我們使用WCF數據服務,使該查詢針對WCF數據服務引用寫的,所以我不能穿越從頂部(系列)到底(雜貨),因爲OData只允許一級選擇。
任何有關優化此代碼的幫助表示讚賞。
AFAIK LinqPad本身不會產生任何查詢,它只是讓EF做到這一點。您確定在LinqPad和您的應用程序中運行查詢時使用相同的EF嗎?你確定查詢是完全一樣的,你的應用程序沒有做任何事情(添加更多的ctiteria等)? –
@AlexeyRaga在LinqPad中,我使用Linq 2 Sql進行ORM,在我的應用程序中使用Entity-Framework,並且在兩種情況下它都是相同的查詢。 –