-
Notifications
You must be signed in to change notification settings - Fork 249
Description
Symptom
When using a checked context (we enabled it by default for the whole solution) some of our queries start to fail with errors like:
System.InvalidOperationException : variable 'x' of type 'CounterEntryEntity`1[ElectricActiveEnergyTwoTariffsCount]' referenced from scope '', but it is not defined
at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
at System.Linq.Expressions.Compiler.VariableBinder.VisitUnary(UnaryExpression node)
at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitUnary(UnaryExpression node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitBinary(BinaryExpression node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitBinary(BinaryExpression node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitBinary(BinaryExpression node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitBinary(BinaryExpression node)
at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitLambda[T](Expression`1 node)
at Cassandra.Data.Linq.CqlExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Cassandra.Data.Linq.CqlExpressionVisitor.GetSelect(Expression expression, Object[]& values)
at Cassandra.Data.Linq.CqlQuery`1.ExecutePagedAsync(String executionProfile)
Analysis
Given a table entity like:
public class Table
{
public short Short { get; init; }
}And a query where filtering like:
short s = 3821;
.Where(t => t.Short == s);Depending on whether a checked or unchecked context is used, the following expression is generated:
- ...
(ConvertChecked(t.Short, Int32) == ConvertChecked(value(<generatedclass>.s, Int32))) - ...
(Convert(t.Short, Int32) == Convert(value(<generatedclass>.s, Int32)))
Proposed Solution
There's four usages of ExpressionType.Convert in the solution (3 in CqlExpressionVisitor and 1 in Mapping\Map.cs.
All perform comparisons like node.NodeType == ExpressionType.Convert
I suggest it should be replaced with
(node.NodeType == ExpressionType.Convert || node.NodeType == ExpressionType.ConvertChecked)Workaround
Instead of writing
.Where(t => t.Short == s);write
.Where(unchecked(t => t.Short == s));Reproduce
I wanted to provide a PR with a reproduction. Unfortunately I fail to compile the solution (both from dotnet CLI and within rider, I get nuget restore errors for Apps.Metrics.Concurrency and I also think there may be some setup steps necessary to get the right target frameworks in the projects, but I haven't found any documentation / the documentation link to the wiki is dead).
However, adding
<PropertyGroup>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>to the test projects might already cause some of the tests to fail.
if not, try a scenario as shown in Analysis, where you filter for a Short value, and put the predicate into a checked context:
short s = 3802;
.Where(checked(t => t.Short == s));