使用以下表格结构(删除了无关列)
create table [Events]
(
ID int not null identity,
Name nvarchar(128) not null,
constraint PK_Events primary key(ID)
)
create table [Donations]
(
ID int not null identity,
EventID int not null,
Amount decimal(10, 2) not null,
constraint PK_Donations primary key(ID),
constraint FK_Donations_Events foreign key(EventID) references [Events](ID) on update no action on delete no action
)
我使用以下Linq-to-Entities查询:
// 1
ents.Donations.Where(d => d.Amount > 25.0m && d.Event.Name.Contains("Run")).ToList();
// 2
ents.Donations.Include("Event").Where(d => d.Amount > 25.0m).ToList();
// 3
ents.Donations.Include("Event").Where(d => d.Amount > 25.0m && d.Event.Name.Contains("Run")).ToList();
生成(来自SQL事件探查器):
-- 1
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[EventID] AS [EventID],
[Extent1].[Amount] AS [Amount]
FROM [dbo].[Donations] AS [Extent1]
INNER JOIN [dbo].[Events] AS [Extent2] ON [Extent1].[EventID] = [Extent2].[ID]
WHERE ([Extent1].[Amount] > 25.0) AND ([Extent2].[Name] LIKE N'%Run%')
-- 2
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[EventID] AS [EventID],
[Extent1].[Amount] AS [Amount],
[Extent2].[ID] AS [ID1],
[Extent2].[Name] AS [Name]
FROM [dbo].[Donations] AS [Extent1]
INNER JOIN [dbo].[Events] AS [Extent2] ON [Extent1].[EventID] = [Extent2].[ID]
WHERE [Extent1].[Amount] > 25.0
-- 3
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[EventID] AS [EventID],
[Extent1].[Amount] AS [Amount],
[Extent3].[ID] AS [ID1],
[Extent3].[Name] AS [Name]
FROM [dbo].[Donations] AS [Extent1]
INNER JOIN [dbo].[Events] AS [Extent2] ON [Extent1].[EventID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[Events] AS [Extent3] ON [Extent1].[EventID] = [Extent3].[ID]
WHERE ([Extent1].[Amount] > 25.0) AND ([Extent2].[Name] LIKE N'%Run%')
为什么在第3个查询中,它是否第二次在LEFT OUTER JOIN
表上生成Events
?虽然查询产生了正确的结果,但似乎很奇怪,为什么EF / LINQ不能在[Extent2]
和SELECT
子句中重用WHERE
,为什么它是LEFT OUTER JOIN
?
我正在使用Visual Studio 2010 sp1 .NET 4,我正在连接到Sql Server 2008 Express。
答案 0 :(得分:7)
左边的连接是为了确保在捐赠指向不存在的事件的情况下Donations表中没有丢失任何行。他们不希望Include关键字产生副作用,导致原始表中缺少行,因此他们必须使用左连接才能确保安全。
关于将表格包括两次,这可能只是EF的限制。你在查询中提到了两次它并不够聪明,无法进行优化。
我不得不说如果你想优化SQL然后编写SQL,不要打扰EF。您正在做的事情可以与反编译C#进行比较,并询问汇编程序为什么没有某种优化。如果您使用EF,那么请关闭它产生的SQL: - )
答案 1 :(得分:0)
不是直接回答您的问题,而是在阅读完其他答案的评论后尝试指出正确的方向:
你拥有保护一些ORM消息所需的一切(包括EF) - 这就是你所说的关于SP的数量和质量的所有内容。任何方法都会遇到问题,包括纯sql,如果sql编写得不好或难以维护。
因此,如果某些ORM(EF等)有时产生无效的代码,这确实会导致性能问题,这就变成了“需求”,即使使用SP也需要解决。
因此,从业务角度看待您的问题 - 您的结构错误,难以维护大量存储过程。可能你的大多数团队都是C#而不是SQL开发人员。
使用ORM将提高代码库的可维护性,并且可以更好地利用C#中所有团队成员的专业知识。
ORM在某些特定情况下生成的错误SQL代码对于使用该技术来说几乎没有“禁止”,除非证明它会产生比解决现有技术更多的问题。