Skip to content

decimal.GetValueOrDefault() not working #2032

Closed
@mohammadfarsi

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

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions