Casting a value to Decimal - c#

Here is my code:
var finiGames = myRepos.Games
.Where(x => x.StatusGameId == (int)StatusGameEnum.Finish
&& x.EndDateTime > DateTime.Today)
.DefaultIfEmpty();
//error line
decimal? sum = finiGames.Sum(x => x.WinCost);
The error I am getting:
Error converting cast a value type "Decimal", because materializuemoe
value is null. The overall result of the type parameter or a request
to use a type that allows the value null.
What is the proper way to get a decimal??

You need to cast the WinCost to a nullable decimal inside the Sum
decimal? sum = finiGames.Sum(x => (decimal?)x.WinCost);

Try adding a ToList() to finiGames. It might kill your performance, but EF probably can't handle the conversion in the data (SQL) layer.

decimal sum = ((decimal?)finiGames.Sum(x => x.WinCost)) ?? 0;

Related

Truncate Time Converting list to nullable

public List<DateTime> CalorieDates(int patientId)
{
using (var db = new DbConn())
{
List<DateTime> query =
db.Calories.Where(d => d.PatientId == patientId && d.FoodId != "initial" && d.DateOfEntry != null)
.Select(d => System.Data.Entity.DbFunctions.TruncateTime(d.DateOfEntry)).Distinct().ToList();
return query;
}
}
Why is this converting my list to nullable datetimes?
Error CS0029 Cannot implicitly convert type
'System.Collections.Generic.List<System.DateTime?>'
to 'System.Collections.Generic.List<System.DateTime>'
How do I prevent this? I do not want a list of nullable datetimes.
For some unknown reason (probably to make the query providers life easier), DbFunctions class does not provide separate TruncateTime overloads for DateTime and DateTime?, but single method with DateTime? argument which handles both cases. However, as a side effect it's changing the expression type to DateTime? even if the argument is DateTime (as it seems to be in your case).
So you need to correct that. Once you know that you are always passing DateTime (hense the result cannot be null), you can simply add .Value at the end of the TruncateTime call and the issue is solved.
.Select(d => System.Data.Entity.DbFunctions.TruncateTime(d.DateOfEntry).Value)
.Select(d => System.Data.Entity.DbFunctions.TruncateTime(d.DateOfEntry))
.Distinct().ToList().Cast<List<DateTime>>()
Like #stuartd says in comments, TruncateTime is probably returning DateTime?; your Select returns IEnumerable<DateTime?> because that's what your lambda gives it from TruncateTime, Distinct() returns the same, and ToList() converts it into List<DateTime?> because, hey that's what IEnumerable<DateTime?>.ToList() returns.
So you end up with a list of DateTime?. That's easy. If you don't want that, Select something else.
Now, I'm going to assume that TruncateTime returns a nullabe type because it may return null. My guess is that its parameter is DateTime?, and it'll only return null if you pass in a null. Since you're passing in a struct, it probably can't return null in your particular usage of it, but I don't know so I'll play it safe.
So you want to convert your enumeration of nullable datetimes to regular ones, without casting any null nullables to regular DateTime. So first filter down to the ones that aren't null, then select their values.
.Select(d => System.Data.Entity.DbFunctions.TruncateTime(d.DateOfEntry))
.Where(d => d.HasValue)
.Select(d => d.Value)
.ToList();
It looks like the db method you are calling to truncate the datetime simply removes the time portion
If that is the case then use the following instead.
List<DateTime> query = db.Calories.Where(d => d.PatientId == patientId && d.FoodId != "initial" && d.DateOfEntry != null)
.Select(d => d.DateOfEntry.Date).Distinct().ToList();

MVC linq to sql sum

Trying to get the values returned from a database based on the sum of a field.
But getting this message:
The cast to value type 'System.Decimal' failed because the
materialized value is null. Either the result type's generic parameter
or the query must use a nullable type.
It is valid for the database to contain no records for that user for that day, hence I went down the nullable route. In the good old days I would have built a Stored Procedure with `ISNULL` in it!!!
This is the basic expression I have:
decimal? foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid).Sum(uf=>(decimal?)uf.quantityAmount ?? 0m);
Googling it came up with the nullable definitions and use of the ?? with the "m" as it's decimal. But still the error persists!
Your collective help will be invaluable as ever. Thanks in advance.
Use the DefaultIfEmpty method. This will fill in a 0 if no value at all can be found.
decimal foodCount = dbContext.fad_userFoods
.Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid)
.Select(uf => uf.quantityAmount)
.DefaultIfEmpty()
.Sum();
Since it's a sum and not average you don't really mind null-values?
Why not simply removing the null-values?
decimal? foodCount = dbContext.fad_userFoods
.Where(uf =>
uf.dateAdded == thisDate &&
uf.userID == thisGuid &&
uf.quantityAmount != null)
.Sum(uf=> uf.quantityAmount);
Use Convert.ToDecimal(), this will handle your null issue.
decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate
&& uf.userID == thisGuid)
.Sum(uf=> Convert.ToDecimal(uf.quantityAmount ?? 0m));
LINQ to Entities does not recognize the method 'System.Decimal
ToDecimal(System.Decimal)' method, and this method cannot be
translated into a store expression.
Edit:
decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate
&& uf.userID == thisGuid)
.Sum(uf=> { decimal result;
decimal.TryParse(uf.quantityAmount,out result);
return result;});
The confusion originates from the fact the Sum in LINQ To Entities is processed a bit different than in LINQ To Objects. Although from declaration it looks like that calling it on a let say decimal will return 0, when the target set is empty actually the SQL SUM function returns NULL, even if the target column is not nullable.
Once you know that, there are two ways of resolving it.
Let say we have a table with decimal column and the original expression is
table.Sum(item => item.Column)
First way is to convert it using the pattern contained in the Maarten answer:
table.Select(item => item.Column).DefaultIfEmpty().Sum()
The second way is to explicitly convert the non nullable type to nullable inside the function and then apply null-coalescing operator to the result:
table.Sum(item => (decimal?)item.Column) ?? 0
Both ways work and produce one and the same result, so use the one that better suits your personal preferences.
For completeness, applying the second approach in your case would be to basically move the ?? 0 outside of the Sum call:
decimal foodCount = dbContext.fad_userFoods
.Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid)
.Sum(uf => (decimal?)uf.quantityAmount) ?? 0;

How do I make a lambda query nullable?

I am getting the following error:
The cast to value type 'System.Int32' failed because the materialized
value is null. Either the result type's generic parameter or the query
must use a nullable type.
How do I make my lambda expression nullable ?
d.QtyOnOrder = db.DieOrders.Where(c=>c.DrawDie.SizeUS==d.SizeUS).Sum(c => c.QtyOpen);
Update: The code below works. Can someone tell me why the Linq expression works and the Lambda does not ?
var dies = from e in db.DieOrders
where e.DrawDieID == d.ID && e.QtyOpen !=null
select e;
var _qtyOpen = dies.Sum(x => x.QtyOpen);
I like #RezaRahmati's suggestion, but an alternative is:
d.QtyOnOrder = db.DieOrders.Where(c=>c.DrawDie.SizeUS==d.SizeUS && d.QtyOpen.HasValue)
.Sum(c => c.QtyOpen);
If all of the QtyOpen are null, then you are summing an empty list which will give you zero.
What I like about Reza's answer however, is that it makes it more explicit that you will set the result to zero if the sum is null.
I think the problem is QtyOnOrder, since Sum can returns null QtyOnOrder should be nullable or use this syntax:
d.QtyOnOrder = db.DieOrders.Where(c=>c.DrawDie.SizeUS==d.SizeUS).Sum(c => c.QtyOpen) ?? 0;
I needed to cast as well, for example the following;
d.QtyOnOrder = db.DieOrders.Where(c=>c.DrawDie.SizeUS==d.SizeUS)
.Sum(c => (int?)c.QtyOpen) ?? 0;
The error indicates that d.QtyOnOrder is not nullable so the solution is to change the class definition so that it is an int? (short hand for Nullable<int>) or to use the null coalescing operator on the left hand side to ensure that null is never returned;
db.DieOrders.Where(c=>c.DrawDie.SizeUS==d.SizeUS).Sum(c => c.QtyOpen) ?? 0;
If the datatype of "QtyOnOrder" is int, You should make it as int?. So now even if sum returns null, code do not generate any error.
int? is a nullable datatype. To know about Nullable types Visit Nullable Types.

using dt.AsEnumerable().Sum for columns having string/null value

I an using following way to get total of a column from a datatable
string total = dt.AsEnumerable().Sum(x => x.Field<decimal>("col1")).ToString();
This works fine when all the values of col1 are number.
My question is- lets consider if any one value of col1 is string or null or anything else other than number, the above code will throw error obviously.
Is there any way to check whether the value is number and use '0' instead if value is not number.
I tried -
string total = dt.AsEnumerable().Sum(x => x.Field<decimal>("col1") is int ? x.Field<decimal>("col1") : 0).ToString();
but not sure if it the correct way.
Please help
If it's not a decimal but a string you would even get a InvalidCastException in the Field<T> method. So you have to know what type it is.
I assume that Col1 can be null, Field<T> supports nullable types:
decimal total = dt.AsEnumerable()
.Sum(r => r.Field<decimal?>("Col1") ?? 0);
or without replacing null with 0:
decimal? total = dt.AsEnumerable()
.Sum(r => r.Field<decimal?>("Col1")); // use total.HasValue and total.Value
Presuming string, you could use decimal.TryParse:
decimal d = 0;
decimal total = dt.AsEnumerable()
.Where(r => decimal.TryParse(r.Field<string>("Col1"), out d))
.Sum(r => d);
If you don't know what type it is you could use object.ToString:
decimal total = dt.AsEnumerable()
.Where(r => !r.IsNull("Col1") && decimal.TryParse(r["Col1"].ToString(), out d))
.Sum(r => d);
Apart from that, why do you store the converted number again in a string variable?

Convert string to int for sum in linq

I have a column requestAmount that is nvarchar(100).
I need to calculate sum :
int? sum = q.Sum(g => g.requestAmount);
I got this error:
Error 26 Cannot convert lambda expression to delegate type
'System.Func<samtaApplication.DbLayer.tblMaterial,int>' because some
of the return types in the block are not implicitly convertible to the
delegate return type
How can I convert string to int?
In linq to entities you can always materialize query first, so you will operate on linq to objects
int? sum = q.AsEnumerable().Sum(g => Int.Parse(g.requestAmount));
Note that it will load whole q from db
EDIT:
if requestAmount is nullable then use:
int? sum = q.AsEnumerable().Sum(g => Convert.ToInt32(g.requestAmount));
Convert.ToInt32 will return 0 when null is passed as parameter
int? sum = q.Sum(g => Int32.Parse(g.requestAmount));
A string can be null or empty, so, keep it safe using a filter with Where and after it applying and Sum , for sample:
int dummy;
int result = q.Where(g => int.TryParse(g.TryParse(g.requestAmount, out dummy))
.Sum(g => int.Parse(g.requestAmount.Trim()));
have you tried using the int.TryParse?

Categories

Resources