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
