9

具有以下表结构(删除了无关列)

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 Profiler):

-- 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%')

为什么在第三个查询中,它会第二次LEFT OUTER JOINEvents表上生成一个?[Extent2]虽然查询产生了正确的结果,但似乎很奇怪,为什么 EF / LINQ 不能在SELECTand子句中重用WHERE,为什么它是LEFT OUTER JOIN?

我正在使用 Visual Studio 2010 sp1 .NET 4,并且正在连接到 Sql Server 2008 Express。

4

2 回答 2

7

左连接将确保在捐赠指向不存在的事件的情况下,捐赠表中不会丢失任何行。他们不希望 Include 关键字具有导致原始表中缺少行的副作用,因此他们必须使用左连接以确保安全。

关于将表格包含两次,这可能只是 EF 的限制。您在查询中提到它两次,它不够聪明,无法进行优化。

不得不说,如果你想优化SQL那就写SQL,别费心EF了。您正在做的事情可以比作反编译 C# 并询问为什么汇编程序没有进行某种优化。如果您使用 EF,那么请对它产生的 SQL 视而不见 :-)

于 2012-07-23T04:39:22.267 回答
0

不是直接回答您的问题,而是在阅读您对其他答案的评论后尝试为您指明正确的方向:

您拥有捍卫某些 ORM 使用(包括 EF)所需的一切——这就是您所说的关于 SP 的数量和质量的全部内容。如果 sql 写得不好或难以维护,任何方法都会有问题,包括纯 sql。

所以,如果某些ORM(EF等)有时会产生效率不高的代码,而这确实会造成性能问题,这就变成了“需求”,需要解决,即使使用SP也是如此。

所以,从业务的角度来看你的问题——你的结构很糟糕,很难维护一堆存储过程。您的团队中的大多数人可能是 C# 而不是 SQL 开发人员。

使用 ORM 将增加代码库的可维护性,并允许更好地使用所有团队成员的 C# 专业知识。

由 ORM 在某些特定场合生成的糟糕 SQL 代码对于使用该技术几乎是“不可行的”,除非证明它会产生比解决现有问题更多的问题。

于 2012-08-01T20:47:07.343 回答