2017-01-16 3 views
3

Ich frage mich, warum Entity Framework eine solche ineffiziente SQL-Abfrage generiert. In meinem Code erwartete ich die WHERE auf das wirken, umfassen:Entity-Framework generiert ineffizientes SQL

db.Employment.Where(x => x.Active).Include(x => x.Employee).Where(x => x.Employee.UserID == UserID) 

aber ich mit einem Doppel-SQL JOIN endete:

SELECT [x].[ID], [x].[Active], [x].[CurrencyID], [x].[DepartmentID], [x].[EmplEnd], [x].[EmplStart], [x].[EmployeeID], [x].[HolidayGroupID], [x].[HourlyCost], [x].[JobTitle], [x].[ManagerID], [x].[WorkScheduleGroupID], [e].[ID], [e].[Active], [e].[Address], [e].[BirthDate], [e].[CitizenshipID], [e].[City], [e].[CountryID], [e].[Email], [e].[FirstName], [e].[Gender], [e].[LastName], [e].[Note], [e].[Phone], [e].[PostalCode], [e].[TaxNumber], [e].[UserID] 
FROM [Employment] AS [x] 
INNER JOIN [Employee] AS [x.Employee] ON [x].[EmployeeID] = [x.Employee].[ID] 
INNER JOIN [Employee] AS [e] ON [x].[EmployeeID] = [e].[ID] 
WHERE ([x].[Active] = 1) AND ([x.Employee].[UserID] = @__UserID_0) 

Ich fand heraus, dass diese Abfrage besser SQL schaffen:

db.Employment.Where(x => x.Active).Where(x => x.Employee.UserID == UserID) 

SELECT [x].[ID], [x].[Active], [x].[CurrencyID], [x].[DepartmentID], [x].[EmplEnd], [x].[EmplStart], [x].[EmployeeID], [x].[HolidayGroupID], [x].[HourlyCost], [x].[JobTitle], [x].[ManagerID], [x].[WorkScheduleGroupID] 
FROM [Employment] AS [x] 
INNER JOIN [Employee] AS [x.Employee] ON [x].[EmployeeID] = [x.Employee].[ID] 
WHERE ([x].[Active] = 1) AND ([x.Employee].[UserID] = @__UserID_0) 

jedoch das Problem hier, die Entitäten referenziert werden nicht von der DB abgerufen.

Warum erzeugen zwei Codes nicht dieselben SQL?

+0

Zuerst sollten Sie ihre Abfragepläne vergleichen - sie könnten identisch sein. –

+0

Ich sehe den Punkt hier nicht, ich benutze EF als eine Abstraktionsschicht über SQL, wenn ich bis zum Abfrageplan gehen muss, könnte ich besser selbst SQL schreiben, anstatt EF es tun zu lassen. – Marko

+0

Sie können beide Bedingungen in einer where-Methode kombinieren, indem Sie den Operator && nach dem Anwenden von Include verwenden. Das sollte eine andere Abfrage erzeugen. –

Antwort

3

Die SQL unterscheidet sich, da die Anweisungen unterschiedlich sind.

Entity Framework ineffizient TSQL produziert, hat es immer. Durch Abstrahieren der Feinheiten, die für SQL mit guter Leistung notwendig sind, und ersetzen sie durch "Gürtel und Klammern" fast immer arbeiten Alternativen Sie Sacrafice Leistung für Dienstprogramm.

Wenn Sie eine gute Leistung benötigen, schreiben die SQL selbst. Dapper funktioniert gut für mich. Sie können nicht realistisch eine "one size fits all" Lösung erwarten, um den besten Code für Ihre spezifische Situation zu finden. Sie können dies auf der ganzen Linie oder nur dort tun, wo Sie es brauchen.

Sofern Sie hochvolumigen oder spezifische Leistungsanforderungen haben wieder mit ihm und verwenden, was Sie am einfachsten zu finden. Wenn Sie Ihre Abfragen auf Ihre Datenbank abstimmen müssen, werden Sie die Details Ihrer Datenbank-Engine erfahren und die Abfragen selbst implementieren. Wenn Sie erwarten, dass die nächste Iteration von Entity Framework das Wundermittel ist, das Ihnen schnellen, effizienten SQL-Datenzugriff mit minimalem Wissen ermöglicht, viel Glück.

P.S.

Off-topic, aber NoSQL wahrscheinlich nicht die Antwort entweder, ist nur eine andere Klasse von Datenbank.

+0

Hinzufügen von SQL-Text ist anders, aber der Abfrageplan kann/wahrscheinlich ist in Ihrem Kontext identisch. +1 für EF erzeugt immer ineffizientes SQL. Sie können immer die teuersten Abfragen überwachen und EF aus diesem Bereich entfernen, indem Sie mit Dapper oder ähnlichem auf anrufende Sprocs umschalten. NoSql ist nicht die Antwort in Ihrem Szenario. –

+0

Nein, der Abfrageplan ist nicht derselbe, das ist das Problem. Ich habe jedoch verstanden, dass ich EF nicht vertrauen kann, um gute SQL für sogar ein bisschen komplexere Abfragen, wie das angezeigte JOIN, zu erzeugen. – Marko

+0

@Marko Ich verstehe Ihre Enttäuschung. Wenn das Datenbankmodell Informationen über Indizes, Datenstatistiken und weitere Einschränkungen enthält, könnte dies theoretisch eine effizientere und sicherere Abfrage ermöglichen. Ich sehe jedoch zwei Nachteile, nämlich eine Menge Arbeit, die eng mit dieser Version von SQL Server verbunden ist und die Art physikalischer Details, die ein ORM versucht, Nicht-Datenbankentwickler zu "schützen". – Jodrell

Verwandte Themen