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 >>> >> >> >
