[CSHARP-506] Throw better exception when comparing a non-nullable field to a nullable value Created: 20/Jun/12 Updated: 14/Dec/16 Resolved: 11/Oct/16 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | 1.4.2, 1.5 |
| Fix Version/s: | 2.4 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Zaid Masud | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||
| Description |
|
Consider the following code: int? nullableFive = 5; In standard LINQ implementations a comparison between a nullable and non-nullable field is valid if the nullable field has a value. If the nullable field does not have a value, the comparison will return false. Workaround: System..InvalidOperationException: The operands for operator 'Equal' do not match the parameters of method 'op_Equality'. at System.Linq.Expressions.Expression.GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, Boolean liftToNull) at System.Linq.Expressions.Expression.Equal(Expression left, Expression right, Boolean liftToNull, MethodInfo method) at System.Linq.Expressions.Expression.MakeBinary(ExpressionType binaryType, Expression left, Expression right, Boolean liftToNull, MethodInfo method, LambdaExpression conversion) at MongoDB.Driver.Linq.ExpressionVisitor.VisitBinary(BinaryExpression node) at MongoDB.Driver.Linq.ExpressionNormalizer.VisitBinary(BinaryExpression node) at MongoDB.Driver.Linq.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.ExpressionVisitor.VisitLambda(LambdaExpression node) at MongoDB.Driver.Linq.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.ExpressionVisitor.VisitUnary(UnaryExpression node) at MongoDB.Driver.Linq.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.ExpressionVisitor.Visit(ReadOnlyCollection1 nodes) at MongoDB.Driver.Linq.ExpressionVisitor.VisitMethodCall(MethodCallExpression node) at MongoDB.Driver.Linq.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.MongoQueryTranslator.Translate(MongoQueryProvider provider, Expression expression) at MongoDB.Driver.Linq.MongoQueryProvider.Execute[TResult](Expression expression) |
| Comments |
| Comment by Robert Stam [ 14/Dec/16 ] | |||||||||
|
See We are reversing the decision that these queries are invalid and will translate them into the closest logical equivalent, even when the value is null (but note that there shouldn't be any nulls in the database if all documents were created using a POCO with a non-nullable member). | |||||||||
| Comment by Githook User [ 11/Oct/16 ] | |||||||||
|
Author: {u'username': u'rstam', u'name': u'rstam', u'email': u'robert@robertstam.org'}Message: | |||||||||
| Comment by Robert Stam [ 11/Oct/16 ] | |||||||||
|
This ticket was originally opened against the 1.x driver, but it is being resolved in the new LINQ implementation in the 2.x driver. The issue arises when you have a document like the following:
And you write a LINQ query like this:
where c.X is not nullable but nullabvleValue is. The correct way to write this query is:
Unfortunately this can't be a compile time error because of the automatic conversions defined by C#, so it is a runtime error. | |||||||||
| Comment by Craig Wilson [ 12/Jul/12 ] | |||||||||
|
After 2 different devs spiked this separately, we can't agree on the correct behavior. This is due to the fact that a non-nullable local field can still be null in the database, and despite the msdn language, it simply doesn't account for this principle. Therefore, we are going to improve the error message in this ticket and require the use of .Value on the local nullable type. | |||||||||
| Comment by Zaid Masud [ 20/Jun/12 ] | |||||||||
|
See official MSDN comment in this issue: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx "When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal)" Also please note that in my code example I used a greater than operator, but the exception was generated for an equality operator. |