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