Just to clarify, I meant I expect (or am not at all surprised that):

   .Where(u => u.UserName == nullVar)

... translates to:

   session
       .CreateQuery("from User u where u.UserName = :name")
       .SetString("name", nullVar)

... which in turn generates the SQL:

   WHERE u.UserName = @p0
   /* with @p0 = NULL */


-----Original Message----- From: David Schmitt
Sent: Tuesday, April 12, 2011 1:57 PM
To: [email protected]
Subject: Re: [nhibernate-development] NH-2583 - Query with || operator and navigations (many-to-one) creates wrong joins


On Tue, 12 Apr 2011 13:17:51 +0100, "Richard Brown \(gmail\)"
<[email protected]> wrote:
... one behavior of Linq2SQL which I cannot qualify other than "very
weird" ...

FWIW, that's pretty much what I would expect a LINQ provider to do.


I would expect:
    session.CreateQuery("from User u where u.UserName is null")

to translate to (using a literal):
    .Where(u => u.UserName == null)


... and I would expect:
    session.CreateQuery("from User u where u.UserName =
:name").SetString("name", nullVar)

... to translate to:
    .Where(u => u.UserName == nullVar)


But maybe that's just me.

I think Harald's point was about the generated SQL, not the intermediate
linq representation.

I'm definitely of the opinion that linq providers should translate .net
semantics into their underlying storage/object provider as faithful as
possible and shield the user from implementation details as much as
possible. I see no reason why the latter expression could not translate to
"(UserName is null and nullVar is null) or (UserName = nullVar)".

Best Regards, David


Richard

-----Original Message----- From: Harald Mueller
Sent: Tuesday, April 12, 2011 12:27 PM
To: [email protected]
Subject: Re: RE: [nhibernate-development] NH-2583 - Query with ||
operator
and navigations (many-to-one) creates wrong joins

Hi - not at all a "dumb question".

Has there ever been a general discussion about how close NH's LINQ
provider actually _wants_ to be to LINQ to objects?

I do not know whether such a discussion + results has been done.
My contribution are (few) conceptual texts about expected semantics /
behavior with examples - see the one I attached to the jira entry, where
I
argued that one should in principle stick to Linq2Objects semantics.
However, Patrick is convinced that we should another semantics ("pure
outer
join semantics" or (||-4)-semantics in my text), for which I have not
yet
written an explaining text ... but I certainly will.

In any case, 100% compatibility to LINQ 2 objects is an illusion.
You'll
never get there, so you might as well not try.

May I suggest that you read my text at the jira entry where I argue for
various, *defined" deviations from LINQ2Objects? The main idea I had is
that
for all cases where LINQ2Objects does *not* throw an exception, the
behaviors are identical; and this *is* feasible at least for navigation
and
the &&, |, !, and Any operators. It depends on what you mean by
"illusion"
-
but as both SQL and Linq(2Objects) semantics are precisely defined and
strong enough, it is certainly possible to have 100% compatibility at
least
under my (BEHAV-3) rule. Still, especially performance arguments might
make
us agree that a differing semantics is better for all practical purposes
-
which is why Patrick suggested a different, deviating (also from
Linq2Objects' non-exceptional behavior) semantics, which I now try to
implement for the logical operators (I'm almost there ...).

Consider the typical
NullReference problem:

a.b.c == x

What's this code supposed to do if a.b is null? In C#, you'd get a
NullReferenceException. Do you want the same in SQL? Why?

See (BEHAV-1) ... (BEHAV-4). Other possibilities are Patrick's "Copy EF
semantics" or your suggestion "Copy Linq2SQL semantics" ...

My suggestion is to copy the behavior of LINQ to SQL and stay as close
to
SQL as you can, because that's easier to handle for the user, and less
likely to bring surprises.

... but both these suggestions obviously have the problem that there is
no
useful definition of these semantics and, especially, their design
targets
(e.g., do they want to follow de'Morgan's laws everywhere - so if they
don't, it's a bug?).

Moreover, I would strongly argue that NHibernate should NOT duplicate
one
behavior of Linq2SQL which I cannot qualify other than "very weird",
namely
the null-constant vs. null-in-a-variable anomaly: (In some version - I
did
not look recently) Linq2SQL creates SQL
   P IS NULL
from Linq
   ...Where(x => x.P == null)...
but it creates
   P = NULL --- which is never true
from
   SomeType nullVar = null;
   ...Where(x => x.P == nullVar)...

And because I do not believe that the Linq2SQL semantics is consistent
(i.e., not contradictory), we should also look at certain conditions,
e.g.
those with !Any ("not any") - these are classical examples where OR
mappings
fail (because some people assume erroneously that "Any" can always by
evaluated with joins and no sub-selects ...).

Also, AFAIK, Linq2SQL can only handle the "table per hierarchy" strategy
for
inheritance - and we would certainly not want to duplicate *this*
limitation
in NHibernate.Linq, wouldn't we?

So, it seems to me that some people ("you"? "we"?) still need to define
(parts of) NHibernate.Linq's semantics better so that it is clear

* what constitues a bug (a deviation from that defined semantics); and
* what is a feature (a designed deviation from Linq2Objects semantics).

And in the course of this discussion one would also establish design
targets
(at least all the meta-rules from logics - like de'Morgan, neutrality of

contradictions for || and tautologies for &&, associativity etc.), as
these
are fundamentally used by all programmers to argue about correctness of
and
find bugs in their application code. Therefore, I completely agree with
you
on the following:

In any case, there needs to be a clear and concise documentation for
translation results. It's just a language that you need to learn before

you use
it. If one has to look up everything in unit tests or try it out, or
even
memorize many inconsistent cases, LINQ becomes a burden. A wiki page
will
do. A reference to unit tests won't.

And I'm quite sure that such a definition needs

(a) (many...) examples

(b) but also a discussion of the "meta-rules" mentioned above - e.g., do
we
want de'Morgan to hold (as it does in propositional logic, C#, and SQL)
or
not? do we require that "false" (or any contradiction) is a neutral
element
for || - i.e., that we always have P || false exactly if P? etc.etc.

[The problem with such rules is that they may have consequences that are
not
immediately visible: contradict each other; or contradict the wanted
behavior of some examples ... but this is well known to all that work in

logics. If you are interested: try to invent all possible consistent
4-valued logics; and for a "very meta" problem of that sort, read about
"material implication" and "strict conditional"].

Anyway, yes, you are right, such a discussion - certainly including
proofs/arguments of wanted / not wanted properties of the ensuing logic
-
plus documentation is a good thing!

Just my two cents.
Your text was, IMHO, more than that :-)

Regards
Harald

Reply via email to