tags:

views:

110

answers:

4

I thought the query was quite trivial, but it's raising a FormatException ("Input string was not in a correct format") nonetheless:

Submissions.Where(s => (false && s.Status == Convert.ToInt16("")))

(of course, in my code, another expression that evaluates to 'false' is located before '&&')

So why is the part after '&&' evaluated, since the first part is always false and the total expression can never evaluate to true?

The situation is particularly strange because only the Convert.ToInt16("") part seems to raise an exception - other parts of my original query of more or less the same structure, like

Submissions.Where(s => (false && s.SubmissionDate <= DateTime.Now))

are evaluated correctly.

+5  A: 

If Submissions is an IQueryable<T>, then this isn't a regular C# delegate, but is an expression tree. Some code (the LINQ provider) has to pull this tree apart and understand it - so if you have oddities in the expressions, then expect odd output.

Marc Gravell
I added an example of a similar query that is evaluated correctly. Why is the first example apparently 'odd' while the second one is not?
dbaw
@hwschuur - See my answer for an explanation of why one works and the other doesn't.
Jeromy Irvine
Simply - it needs to create TSQL for the expression. At a guess, it is breaking while trying to evaluate the Convert.ToInt16("") into either a constant (to go into the TSQL string) or a parameter value.
Marc Gravell
+2  A: 

Well based on your answer to my question in the comments, since it's Linq to Sql, it's not actually a delegate. I tried recreating it using Linq to Objects, and sure enough there was no issue at all. VS actually pointed out that "Unreachable code detected". Since in your case it's actually Linq to Sql, then it's building up an expression tree, in which case it has to decipher all of it and all bets are off.

BFree
A: 

Suggestion: use a static Int16 to hold the result of Convert.ToInt16(""), then refer to the static in the predicate.

Better still, do you know what the result of Convert.ToInt16("") is? Yes? Then use that instead. For instance, if it's 0, then say s.Status == 0. You could even make that a constant.

John Saunders
+5  A: 

As the others have pointed out, LINQ to SQL code gets pulled apart into an expression tree before being run as SQL code against the database. Since SQL does not necessarily follow the same short-circuit boolean rules as C#, the right side of your expression code might get parsed so that the SQL can be constructed.

From MSDN:

C# specifies short circuit semantics based on lexical order of operands for logical operators && and ||. SQL on the other hand is targeted for set-based queries and therefore provides more freedom for the optimizer to decide the order of execution.

As for why you're getting an exception with this code, Convert.ToInt16("") will always throw precisely that exception because there's no way to convert an empty string into an integer. Your other example doesn't attempt an invalid conversion, hence it runs without a problem.

Jeromy Irvine
Now it is clear to me. Thanks.
dbaw