2012-07-23 4 views
8

Mit der folgenden Tabelle Struktur (Fremd Spalten entfernt) verbindeneinschließen und wo Prädikat Ursache kommt links statt inneren

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 
) 

Ich verwende die folgenden Linq-to-Entities-Abfragen:

// 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(); 

Produziert (aus einem 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%') 

Warum in der dritten Abfrage, generiert es ein LEFT OUTER JOIN auf der Events Tabelle ein zweites Mal? Während die Abfrage korrekte Ergebnisse produziert, scheint es seltsam, warum EF/LINQ nicht wieder verwenden [Extent2] in SELECT und WHERE Klausel, und warum ist es ein LEFT OUTER JOIN?

Ich verwende Visual Studio 2010 SP1 .NET 4 und verbinde mich mit Sql Server 2008 Express.

Antwort

6

Der linke Join würde sein, um sicherzustellen, dass keine Zeilen in der Tabelle "Spenden" fehlen, falls eine Spende auf ein nicht vorhandenes Ereignis zeigt. Sie möchten nicht, dass das Include-Schlüsselwort den Nebeneffekt hat, dass Zeilen in der ursprünglichen Tabelle fehlen, sodass sie zur Sicherheit einen Linksbündnis verwenden müssen.

In Bezug auf die Aufnahme der Tabelle zweimal ist dies wahrscheinlich nur eine Einschränkung der EF. Sie erwähnen es zweimal in Ihrer Abfrage und es ist nicht schlau genug, um die Optimierung zu tun.

Ich muss sagen, dass, wenn Sie SQL optimieren möchten dann schreiben Sie SQL, nicht mit EF kümmern. Was Sie tun, könnte mit dem Dekompilieren von C# verglichen werden und fragen, warum der Assembler keine bestimmte Optimierung hat. Wenn Sie EF Fahren Sie dann den Augen, was SQL erzeugt es :-)

+1

Die zweite Abfrage verwendet 'Include' und erzeugt noch keinen linken Join. – Matthew

+0

Sehr gute Frage, das habe ich nicht bemerkt. Das scheint mir von vorne zu sein. Die zweite Abfrage sollte einen linken Join enthalten, damit Include keine Nebenwirkungen verursacht und die dritte Abfrage einen inneren Join aufweist, da sie ohnehin eine Ereigniszeile benötigt. – MikeKulls

+0

Ein linker Join würde Sinn ergeben, wenn es sich um eine Spalte mit Nullwert handeln könnte oder wenn ich keine referenzielle Integrität darauf hätte. – Matthew

0

keine direkte Antwort auf Ihre Frage, aber ein Versuch, Sie in die richtige Richtung zu zeigen, nachdem Ihre Kommentare zu den anderen Antworten zu lesen:

Sie haben alles, was Sie brauchen, um eine ORM-Nachricht zu verteidigen (inkl. EF) - das ist alles, was Sie über die Quantität und Qualität der SPs gesagt haben. Jeder Ansatz wird Probleme haben, einschließlich pure sql, wenn dieser sql nicht gut geschrieben oder schwer zu pflegen ist.

Also, wenn einige ORM (EF, etc.) manchmal nicht-effizienten Code produziert, und dies wirklich Leistungsprobleme verursacht, wird dies "Anforderung", und muss gelöst werden, auch mit SP.

Also, schauen Sie sich Ihre Probleme aus Business-Perspektive - Sie haben schlecht strukturierte und schwer zu pflegen Haufen gespeicherter Prozeduren. Wahrscheinlich ist der Großteil Ihres Teams C# und nicht SQL-Entwickler.

Die Verwendung von ORM erhöht die Wartbarkeit der Codebasis und ermöglicht eine bessere Nutzung des gesamten Fachwissens der Teammitglieder in C#.

Schlechter SQL-Code, der von ORM zu bestimmten Anlässen erzeugt wird, ist für die Verwendung der Technologie kaum "no-go", es sei denn, es hat bewiesen, dass es mehr Probleme als die Lösung bestehender Probleme schafft.

+0

Ich würde anders herum schauen. Wenn Entwickler in SQL unerfahren sind, müssen sie erfahren werden. Sie schreiben schließlich Datenbank-Apps und ein Mangel an SQL-Wissen ist in diesen Tagen inakzeptabel. Die eine Sache, die sie nicht brauchen, ist mehr Gründe, sql zu vermeiden. – MikeKulls

+0

Sie sind definitiv nicht unerfahren bei SQL, die Anwendung hat ~ 9 Jahre der ständigen Entwicklung durchlaufen (angefangen mit ASP.net 1.0), viele verschiedene Entwickler. Die Anwendung, so wie sie jetzt steht, hat keine Trennung von Bedenken, gespeicherte Prozeduren werden innerhalb des Codes direkt aufgerufen. Deshalb suche ich nach etwas, das sehr einfach zu verwalten ist, hauptsächlich weil ich glaube, dass die Organisation der gespeicherten Procs gerade eine Abschreibung ist. – Matthew

Verwandte Themen