Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The null value cannot be assigned to a member with type decimal which is a non-nullable value type

An exception occurs when the following IQueryable is enumerated:

from record in dataContext.SomeTable
select Convert.ToDecimal(record.nullableDecimalColumn);

The error is an InvalidOperationException:

The null value cannot be assigned to a member with type decimal which is a non-nullable value type

The documentation for Convert.ToDecimal says that it converts null to 0, so it looks like it should work correctly.

like image 270
Sam Avatar asked Sep 12 '13 06:09

Sam


People also ask

Can we assign a null value to value type data type?

As you know, a value type cannot be assigned a null value. For example, int i = null will give you a compile time error. C# 2.0 introduced nullable types that allow you to assign null to value type variables.

What is a non Nullable value?

Nullable variables may either contain a valid value or they may not — in the latter case they are considered to be nil . Non-nullable variables must always contain a value and cannot be nil . In Oxygene (as in C# and Java), the default nullability of a variable is determined by its type.

How to assign null value in C#?

In C#, you can assign the null value to any reference variable. The null value simply means that the variable does not refer to an object in memory. You can use it like this: Circle c = new Circle(42); Circle copy = null; // Initialized ... if (copy == null) { copy = c; // copy and c refer to the same object ... }

What is Nullable data type in C#?

C# provides a special data types, the nullable types, to which you can assign normal range of values as well as null values. For example, you can store any value from -2,147,483,648 to 2,147,483,647 or null in a Nullable<Int32> variable. Similarly, you can assign true, false, or null in a Nullable<bool> variable.


Video Answer


2 Answers

If you wrote Query like this

tot_vat_amt = _pd.Where(x => x.VAT == 4m).Sum(x =>x.amount)

Replace with

tot_vat_amt = _pd.Where(x => x.VAT == 4m).Sum(x =>(double?)x.amount)

Hope this will help you

like image 83
Chintan Avatar answered Sep 20 '22 23:09

Chintan


LINQ to SQL wasn't translating the ToDecimal method equivalently; it wasn't tolerating NULL. I fixed this by using GetValueOrDefault instead of Convert.ToDecimal:

from record in dataContext.SomeTable
select record.nullableDecimalColumn.GetValueOrDefault();

This caused the correct SQL to be produced, so the exception no longer occurred.

Here is my understanding of why this happens. LINQ to SQL and Entity Framework provide face-value semantic translation rather than literal translation. In this example, Convert.ToX is translated directly to CONVERT or CAST in SQL. This is the SQL equivalent translation, but not literal because it does not include the fine details of how .NET Convert.ToX operates. Specifically, the .NET one converts nulls to default values.

This is a symptom of the fact that the code didn't express what its author (who wasn't me) was really trying to do, which was convert nulls to default values rather than convert between data types.

In my opinion, this is also a symptom of IQueryable being a leaky and unreliable abstraction. I personally think it would be better not to use it in the first place and instead use something that's designed better such as a normal/fluent API. I think IQueryable completely violates the interface segregation principle because it allows an unlimited range of queries to be used despite only a limited subset being supported.

like image 27
Sam Avatar answered Sep 21 '22 23:09

Sam