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 プロファイラーから) 以下を生成します。

-- 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 JOIN3 番目のクエリで、2 回目のEventsテーブルで が生成されるのはなぜですか? [Extent2]クエリは正しい結果を生成しますが、奇妙に思えます。EF / LINQがSELECTandWHERE句で再利用できないのはなぜLEFT OUTER JOINですか。

Visual Studio 2010 sp1 .NET 4 を使用しており、Sql Server 2008 Express に接続しています。

4

2 に答える 2

7

左結合は、寄付が存在しないイベントを指している場合に、Donations テーブルから行が欠落しないようにするためのものです。彼らは、Include キーワードが元のテーブルから行が失われるという副作用を望んでいないため、安全のために左結合を使用する必要があります。

テーブルを 2 回含めることに関しては、これはおそらく EF の制限にすぎません。クエリで 2 回言及していますが、最適化を行うほどスマートではありません。

SQL を最適化してから SQL を記述したい場合は、EF を気にしないでください。あなたがしていることは、C# を逆コンパイルして、アセンブラーが特定の最適化を行わない理由を尋ねることに例えることができます。EF を使用する場合は、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 に答える