这个问题来自question昨天我问过为什么在我的实体上使用连接查询产生了非常复杂的SQL。似乎执行这样的查询:
var query = from ev in genesisContext.Events
join pe in genesisContext.People_Event_Link
on ev equals pe.Event
where pe.P_ID == key
select ev;
生成了在数据库上运行需要18秒的可怕SQL,而通过where子句(有点像ANSI SQL之前的语法)加入实体花了不到一秒的时间来运行并产生相同的结果
var query = from pe in genesisContext.People_Event_Link
from ev in genesisContext.Events
where pe.P_ID == key && pe.Event == ev
select ev;
我已经谷歌搜索了但仍然不明白为什么第二个会产生不同的SQL到第一个。有人可以向我解释一下这个区别吗?我什么时候应该使用join关键字
这是我在查询中使用Join并运行18秒时生成的SQL:
SELECT
1 AS [C1],
[Extent1].[E_ID] AS [E_ID],
[Extent1].[E_START_DATE] AS [E_START_DATE],
[Extent1].[E_END_DATE] AS [E_END_DATE],
[Extent1].[E_COMMENTS] AS [E_COMMENTS],
[Extent1].[E_DATE_ADDED] AS [E_DATE_ADDED],
[Extent1].[E_RECORDED_BY] AS [E_RECORDED_BY],
[Extent1].[E_DATE_UPDATED] AS [E_DATE_UPDATED],
[Extent1].[E_UPDATED_BY] AS [E_UPDATED_BY],
[Extent1].[ET_ID] AS [ET_ID],
[Extent1].[L_ID] AS [L_ID]
FROM [dbo].[Events] AS [Extent1]
INNER JOIN [dbo].[People_Event_Link] AS [Extent2] ON EXISTS (SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent3].[E_ID] AS [E_ID]
FROM [dbo].[Events] AS [Extent3]
WHERE [Extent2].[E_ID] = [Extent3].[E_ID] ) AS [Project1] ON 1 = 1
LEFT OUTER JOIN (SELECT
[Extent4].[E_ID] AS [E_ID]
FROM [dbo].[Events] AS [Extent4]
WHERE [Extent2].[E_ID] = [Extent4].[E_ID] ) AS [Project2] ON 1 = 1
WHERE ([Extent1].[E_ID] = [Project1].[E_ID]) OR (([Extent1].[E_ID] IS NULL) AND ([Project2].[E_ID] IS NULL))
)
WHERE [Extent2].[P_ID] = 291
这是使用ANSI Style语法生成的SQL(并且与我自己编写SQL时要写的相当接近):
SELECT * FROM Events AS E INNER JOIN People_Event_Link AS PE ON E.E_ID=PE.E_ID INNER JOIN PEOPLE AS P ON P.P_ID=PE.P_ID
WHERE P.P_ID = 291
答案 0 :(得分:4)
以上两种查询都不完全“正确”。在EF中,使用关系属性代替上述任何一种通常是正确的。例如,如果在一个名为Person.PhoneNumbers的属性中有一个与PhoneNumbers有一对多关系的Person对象,则可以写:
var q = from p in Context.Person
from pn in p.PhoneNumbers
select pn;
EF将为您构建联接。
就上述问题而言,生成的SQL不同的原因是因为表达式树是不同的,即使它们产生相同的结果。表达式树映射到SQL,您当然知道您可以编写不同的SQL,这些SQL会产生相同的结果,但性能会有所不同。当您编写一个很好的“常规”EF查询时,该映射旨在生成不错的SQL。
但是映射不是那么聪明,不能采用非常规的查询并对其进行优化。在第一个查询中,您声明对象必须是等效的。在第二步中,您声明 ID属性必须是等效的。我上面的示例查询说“只需获取此一条记录的详细信息”。 EF主要用于处理我显示的方式,但也可以很好地处理标量等效。