Tiny clarification in option C... should read Equals(Data,
nullVariable), not Equals(nullVariable, NULL).

On Fri, Oct 29, 2010 at 1:50 AM, Patrick Earl <[email protected]> wrote:
> I should note there's a sub-decision I forgot to mention... how to
> handle a variable with known null content.
>
> int? nullVariable = null;
> int? notNullVariable = 1;
>
> .Where(x => x.Data == nullVariable)
> .Where(x => x.Data == notNullVariable)
>
> In EF and LINQ to SQL, these both generate:  Data = @p0, where @p0 is
> NULL.  This maintains consistency with the model of not being able to
> compare against null "things" directly.  The only special case with
> the null behavior is comparing directly with the null literal (==
> null, != null generate IS NULL and IS NOT NULL).
>
> In NHibernate, it currently generates IS NULL for the first, and = @p0
> for the second.
>
> Again there are two options for handing the case of Data == nullVariable:
>
> Option C:  Generate = @p0.  This is consistent with EF and LINQ to
> SQL.  If users want to get the IS NULL behavior, they could use
> Equals(variable, NULL) as discussed earlier.
> Option D:  Generate IS NULL.  This is often what might be expected,
> but it is inconsistent with how the equality operator works when the
> "variable" is a database column for example.
>
> My vote is for consistency in operator semantics, with the only
> special cases being == null and != null.
>
> For this, I vote for C.
>
>          Patrick Earl
>
> On Fri, Oct 29, 2010 at 1:29 AM, Richard Brown (gmail)
> <[email protected]> wrote:
>> I think option B has come about because some programmers (misguidedly, IMHO)
>> think they can test their queries in-memory, and expect the generated SQL to
>> behave exactly the same as linq-to-objects.  I'm sure it's been mentioned
>> several times in the users group that the preferred way to test queries is
>> against a 'real' database, which is why I'm not a huge fan of option B.
>>
>> In addition, having used the previous NH-contrib linq provider in a largish
>> production system, I noted that a not insignificant amount of time was spent
>> trying various combinations of linq expression, while sitting with either
>> NH-Prof or the log files, to try and figure out how to get the desired SQL
>> to come out the other side.
>>
>> So I think (and I hope I'm not proven wrong in the future), that opaqueness
>> wins ... i.e., that the generated SQL should be as predictable as possible,
>> certainly for simple queries.
>>
>> So +1 for option A.
>>
>>
>> -----Original Message----- From: Patrick Earl
>> Sent: Friday, October 29, 2010 7:20 AM
>> To: [email protected]
>> Subject: Re: [nhibernate-development] Linq Null Operations
>>
>> Okay, here's what happens in the various frameworks currently:
>>
>> Linq to SQL:
>> A == B produces A = B
>> A != B produces A <> B
>> Equals(A,B) produces (A is null and B is null) or (A is not null and B
>> is not null and A = B)
>>
>> Entity Framework:
>> A == B produces A = B
>> A != B produces A <> B
>> Equals(A,B) produces an exception.  There's no easy way to do the long
>> form as far as I can see.
>>
>> NHibernate:
>> A == B produces (A is null and B is null) or (A = B) [which
>> incorrectly produces nulls sometimes]
>> A != B produces (A is null) and (B is not null) or (A is not null) and
>> (B is null) or A<>B [which also incorrectly produces nulls sometimes]
>> Equals(A,B) produces an exception.
>>
>> A == null and A != null generate A is null and A is not null in all
>> frameworks.
>>
>> Now that we know how the systems work, consider the other frames of
>> reference.
>>
>> For .NET developers, they're used to being able to compare nulls
>> directly.  See this connect bug report that also shows many people
>> having issues again and again with this mismatch.  They consider it to
>> be a problem with the linq system.
>>
>> http://connect.microsoft.com/data/feedback/details/607404/entity-framework-and-linq-to-sql-incorrectly-handling-nullable-variables
>>
>> In SQL however, developers tend to write plain A = B most frequently,
>> sometimes using coalesce or other null checks as needed.  As an
>> example from our code base, the majority of the time we don't need to
>> compare against nulls.
>>
>> So, it's clear there are valid reasons for going either way.  I would
>> propose that it would be best to follow the nature of SQL, copying the
>> behavior of Linq to SQL and the Entity Framework.  Though it will lead
>> to some confusion for users, it won't lead to unexpectedly complicated
>> queries from simple expressions.
>>
>> So, here are the basic options.
>>
>> Option A:  Simple equality.  Follows SQL, Linq to SQL, and EF, but is
>> sometimes confusing.
>> Option B:  C#-style equality with long expression.  Rules are clear
>> but generated SQL is sometimes poor.
>>
>> This choice should be made deliberately.
>>
>> My vote is for A.
>>
>>       Patrick Earl
>>
>> On Thu, Oct 28, 2010 at 9:17 PM, Patrick Earl <[email protected]> wrote:
>>>
>>> Ultimately, I'm fine diverging from the standard way of doing things
>>> to make null equality work as expected from an object programmer's
>>> perspective.  However, in cases where the programmer is sure there
>>> cannot be nulls, it would be great to have some technique to specify
>>> that A = B should be used instead of (A is null and B is null) or (A
>>> is not null and B is not null and A = B)  [ See
>>> http://216.121.112.228/browse/NH-2398 ].  If the decision is to go the
>>> "object emulation route," as is in the code so far, I'd at least like
>>> to allow the expression to be a dialect-specific thing, since some
>>> databases can use IS DISTINCT FROM or <=>.
>>>
>>> Things seem a little slow around the list this week.  Maybe everyone's
>>> in crazy work mode like we've been recently. :)
>>>
>>>       Patrick Earl
>>>
>>
>>
>

Reply via email to