Hintergrund: Ich arbeite an einem System, um eine interne Kundenliste zu bereinigen und herauszufinden, E-Mail-Adressen von Kontakten, wo wir die E-Mail-Adresse von jemand anderem bereits bei dieser Firma haben. Um dies zu tun, ich habe (vereinfacht) 3 Tabellen:Warum enthält Linq das Generieren dieses SQL?
Kontakte:
ID
CompanyId
Email
Domain
EmailDomains:
ID
Domain
EmailFormat
EmailFormatConfirmed
Ich habe eine manuelle Routine, die sagt, angesichts der Unternehmen, finden Sie den nächsten Kontakt, wo wir ihren Domain-Namen haben, aber nicht ihre E-Mail-Adresse:
int companyId = 53;
var emails = Contacts.Where(p => p.companyId == companyId
&& p.Email == null
&& !string.IsNullOrEmpty(p.Domain)).Select(p => p.Domain);
var domain =
EmailDomains.FirstOrDefault(
d => !d.EmailFormatConfirmed
&& !string.IsNullOrEmpty(d.Domain)
&& emails.Contains(d.Domain));
Diese Abfrage läuft sehr langsam und auf dem SQL-Check-out generiert:
-- Region Parameters
DECLARE @p__linq__0 Int = 53
-- EndRegion
SELECT TOP (1)
[Extent1].[Id] AS [Id],
[Extent1].[Domain] AS [Domain],
[Extent1].[EmailFormat] AS [EmailFormat],
[Extent1].[EmailFormatConfirmed] AS [EmailFormatConfirmed],
FROM [dbo].[EmailDomain] AS [Extent1]
WHERE ([Extent1].[EmailFormatConfirmed] <> 1)
AND (NOT (([Extent1].[Domain] IS NULL) OR ((LEN([Extent1].[Domain])) = 0)))
AND (EXISTS (
SELECT 1 AS [C1]
FROM [dbo].[Contacts] AS [Extent2]
WHERE ([Extent2].[CompanyId] = @p__linq__0)
AND ([Extent2].[Email] IS NULL)
AND (NOT (([Extent2].[Domain] IS NULL) OR ((LEN([Extent2].[Domain])) = 0)))
AND (([Extent2].[Domain] = [Extent1].[Domain]) OR (([Extent2].[Domain] IS NULL) AND ([Extent1].[Domain] IS NULL)))
))
ich, dass der säumige Teil OR (([Extent2].[Domain] IS NULL) AND ([Extent1].[Domain] IS NULL))
Klausel am Ende der existiert, ist zu sehen. Warum sollte das überhaupt dort sein? Ich kann nicht verstehen, wie es gültig ist, und wenn ich den Sql von Hand kodiere (was derzeit der Fall ist, auf den ich zurückgreifen muss), wäre es nicht so. Fehle ich etwas Offensichtliches? Das Entfernen dieser die Abfrage sehr schnell laufen lässt (wie zu erwarten wäre - es gibt eine Menge von null Domänen sind, die effektiv hier Kreuz verbunden werden)
Es ist notwendig, 'NULL' Fälle zu behandeln, da in SQL' NULL! = NULL' ist. Dies führt zu 'value1 = value2 OR (Wert1 IST NULL UND Wert2 IST NULL)'. – Maarten
Welche Version von EF verwenden Sie? Vielleicht können Sie [this] (https://msdn.microsoft.com/en-us/library/system.data.objects.objectcontextoptions.usecsharpnullcomparisonbehavior.aspx) verwenden, siehe auch [this] (http://stackoverflow.com)/a/2541042/261050) – Maarten
@Maarten - mit EF6.Ich bin jedoch nicht sicher, ob Sie das Problem bekommen - ich könnte dies in Sql als CTE oder Sub Query schreiben, die die Kontakt-Domains für das angegebene Unternehmen ohne E-Mails abrufen und dann innerlich mit der EmailDomains-Tabelle verbinden würde. Ich verstehe null! = Null, aber ich möchte einfach keine Nullen berücksichtigen – Macros