Background: I am working on a system to clean up an internal customer list and figure out email addresses of contacts where we have the email address of someone else already at that company. In order to do this I have (simplified) 3 tables:
Contacts:
ID
CompanyId
Email
Domain
EmailDomains:
ID
Domain
EmailFormat
EmailFormatConfirmed
I have a manual routine which is saying, given the company, find me the next contact where we have their domain name but not their email address:
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));
This query runs very slowly and on checking out the Sql generated:
-- 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)))
))
I can see that the offending part is OR (([Extent2].[Domain] IS NULL) AND ([Extent1].[Domain] IS NULL))
at the end of the exists clause. Why would this even be there? I can't understand how it is valid, and if I were hand coding the Sql (which currently is what I am going to have to fallback on) It wouldn't be. Am I missing something obvious? Removing this makes the query run very fast (as would be expected - there are a lot of null domains which effectively are being cross joined here)