tags:

views:

289

answers:

4

Why does this work:

result = (from e in db.CampaignCodes where e.Code.Equals("") && 
e.Domain.Equals(null) select e).FirstOrDefault();

But not (result is null):

String code = "";
String domain = null;

result = (from e in db.CampaignCodes where e.Code.Equals(code) &&
 e.Domain.Equals(domain) select e).FirstOrDefault();

??

+2  A: 

a null string - domain - isn't the same as just passing null?

Iain
+6  A: 

To expand on Iain's answer:

Depending on what overloads of e.Domain.Equals() there are, passing a null string variable may hit a different one than passing null? I'm not sure what the rules would be here, but I suspect the compiler might prefer an e.Domain.Equals(object variable) to e.Domain.Equals(string variable) when explicitly given "just" null, rather than a string variable that has been set as null?

Rob
+2  A: 

That does indeed sound quite odd. LINQ to SQL may well notice the difference between getting the value from a variable and getting it from a constant, but I wouldn't have expected it to make any difference.

I strongly recommend that whenever LINQ to SQL appears to be behaving oddly, you turn the context logging on and see what query it's actually executing in each case.

EDIT: The other answers around the overloading aspect are really interesting. What happens if you declare the domain variable as type object instead of string in the second query, or cast the null to string in the first query?

Jon Skeet
Not having gotten around to using LinqToSql yet, my answer is supposition - which probably means I'm overly complicating things! Yours is definitely the more "practically useful" answer =)
Rob
Certainly turning the log on should take at least *some* of the mystery away :)
Jon Skeet
I don't remember exactly what was the problem, but we did have some issues with comparing for null values. SQL compared things that were null a bit differently than is done in C#.
Svish
Think it was something with null != null... or something...
Svish
Yes, SQL null values aren't equal to anything else.
Jon Skeet
@Svish @Rob @Niels @Jon: See http://stackoverflow.com/questions/682429/how-can-i-query-for-null-values-in-entity-framework
BlueRaja - Danny Pflughoeft
+1  A: 

Figuread it out through logging, these are my results:

I get the following results:

Works:

(from e in CampaignCodes where e.Code.Equals(code) && e.Domain.Equals(null) select e).FirstOrDefault().Dump();

SELECT TOP (1) [t0].[Id], [t0].[Code], [t0].[Domain], [t0].[ClientId], [t0].[CampaignId], [t0].[PathId], [t0].[DescriptionText], [t0].[DeleteFlag], [t0].[Created]
FROM [CampaignCodes] AS [t0]
WHERE ([t0].[Code] = @p0) AND ([t0].[Domain] IS NULL)
-- @p0: Input NVarChar (Size = 0; Prec = 0; Scale = 0) []
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Doesn't Work:

(from e in CampaignCodes where e.Code.Equals(code) && e.Domain.Equals(domain) select e).FirstOrDefault().Dump();

SELECT TOP (1) [t0].[Id], [t0].[Code], [t0].[Domain], [t0].[ClientId], [t0].[CampaignId], [t0].[PathId], [t0].[DescriptionText], [t0].[DeleteFlag], [t0].[Created]
FROM [CampaignCodes] AS [t0]
WHERE ([t0].[Code] = @p0) AND ([t0].[Domain] = @p1)
-- @p0: Input NVarChar (Size = 0; Prec = 0; Scale = 0) []
-- @p1: Input NVarChar (Size = 0; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.

8

so

By rewriting my linq2sql to:

(from e in CampaignCodes where e.Code.Equals(code) && ((domain==null && e.Domain.Equals(null))||e.Domain.Equals(domain)) select e).FirstOrDefault().Dump();

I get:

SELECT TOP (1) [t0].[Id], [t0].[Code], [t0].[Domain], [t0].[ClientId], [t0].[CampaignId], [t0].[PathId], [t0].[DescriptionText], [t0].[DeleteFlag], [t0].[Created]
FROM [CampaignCodes] AS [t0]
WHERE ([t0].[Code] = @p0) AND ([t0].[Domain] = @p1)
-- @p0: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [test]
-- @p1: Input NVarChar (Size = 14; Prec = 0; Scale = 0) [mydomain.se]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

When domain isn't null and:

SELECT TOP (1) [t0].[Id], [t0].[Code], [t0].[Domain], [t0].[ClientId], [t0].[CampaignId], [t0].[PathId], [t0].[DescriptionText], [t0].[DeleteFlag], [t0].[Created]
FROM [CampaignCodes] AS [t0]
WHERE ([t0].[Code] = @p0) AND (([t0].[Domain] IS NULL) OR ([t0].[Domain] = @p1))
-- @p0: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [test]
-- @p1: Input NVarChar (Size = 0; Prec = 0; Scale = 0) [Null]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

When it is.

But I'd hoped that there would be a nices methods for this...

Niels Bosma