Closed
Description
Hi,
We have a problem while trying to use a nullable decimal column and cast it in to decimal property in model using GetValueOrDefault()
Exception message:
TryExpression is not supported as a child expression when accessing a member on type 'System.Nullable`1[System.Decimal]' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression.
Stack trace:
System.NotSupportedException
HResult=0x80131515
Message=TryExpression is not supported as a child expression when accessing a member on type 'System.Nullable`1[System.Decimal]' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression.
Source=System.Core
StackTrace:
at System.Linq.Expressions.Compiler.StackSpiller.RequireNotRefInstance(Expression instance)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.MemberAssignmentRewriter..ctor(MemberAssignment binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.BindingRewriter.Create(MemberBinding binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMemberInitExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteVariableAssignment(BinaryExpression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteBlockExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpressionFreeTemps(Expression expression, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteInvocationExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpressionFreeTemps(Expression expression, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
at System.Linq.Expressions.Expression`1.Compile()
at LinqToDB.Linq.QueryRunner.Mapper`1.Map(IQueryRunner queryRunner, IDataReader dataReader) in C:\Projects\linq2db\Source\LinqToDB\Linq\QueryRunner.cs:line 67
at LinqToDB.Linq.QueryRunner.<ExecuteQuery>d__10`1.MoveNext() in C:\Projects\linq2db\Source\LinqToDB\Linq\QueryRunner.cs:line 348
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at LinqToDB.Linq.Builder.FirstSingleBuilder.FirstSingleContext.<>c__DisplayClass3_0`1.<GetFirstElement>b__0(IDataContext db, Expression expr, Object[] ps) in C:\Projects\linq2db\Source\LinqToDB\Linq\Builder\FirstSingleBuilder.cs:line 116
at LinqToDB.Linq.ExpressionQuery`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression) in C:\Projects\linq2db\Source\LinqToDB\Linq\ExpressionQuery.cs:line 165
at ConsoleApp3.db.Exec2() in C:\project\source\repos\ConsoleApp3\ConsoleApp3\db.cs:line 58
at ConsoleApp3.Program.Main(String[] args) in C:\project\source\repos\ConsoleApp3\ConsoleApp3\Program.cs:line 14
This exception was originally thrown at this call stack:
System.Linq.Expressions.Compiler.StackSpiller.RequireNotRefInstance(System.Linq.Expressions.Expression)
System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.MemberAssignmentRewriter.MemberAssignmentRewriter(System.Linq.Expressions.MemberAssignment, System.Linq.Expressions.Compiler.StackSpiller, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.BindingRewriter.Create(System.Linq.Expressions.MemberBinding, System.Linq.Expressions.Compiler.StackSpiller, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteMemberInitExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteVariableAssignment(System.Linq.Expressions.BinaryExpression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
System.Linq.Expressions.Compiler.StackSpiller.RewriteBlockExpression(System.Linq.Expressions.Expression, System.Linq.Expressions.Compiler.StackSpiller.Stack)
...
[Call Stack Truncated]
Steps to reproduce
Suppose we have this table:
public class MyTable
{
[Column("MYDECIMAL"), Nullable] public decimal? MYDECIMAL { get; set; }
}
public class MyDb : DataConnection
{
public ITable<MyTable> MyTable { get { return GetTable<MyTable>(); } }
}
And this is sample model we want to use
public class MyModel
{
public decimal MyDecimal { get; set; }
}
Let's write simple test code
public void Exec2()
{
using (var db = new MyDb("Data Source=DB;User ID=myuser;Password=mypassword;"))
{
var q = db.MyTable.Select(x => new MyModel
{
MyDecimal = x.MYDECIMAL.GetValueOrDefault() //Error Here
}).First();
}
}
After running the code we get an exception
Exception message:
TryExpression is not supported as a child expression when accessing a member on type 'System.Nullable`1[System.Decimal]' because it is a value type. Construct the tree so the TryExpression is not nested inside of this expression.
But if we call it in this way it works without any exception.
public void Exec2()
{
using (var db = new MyDb("Data Source=DB;User ID=myuser;Password=mypassword;"))
{
var q = db.MyTable.Select(x => new MyModel
{
MyDecimal = x.MYDECIMAL ?? 0 //No Error
}).First();
}
}
Or if it was integer instead of decimal it works fine.
Environment details
linq2db version: 2.9.5
Database Server: Oracle 12.1.0.1.0
Database Provider: Oracle Managed
Operating system: Windows 10 1909 x64
.NET Framework: 4.7.2