How to do Linq aggregates when there might be an empty set?
aggregate, c#, linq, linq-to-sql
Solution
I can reproduce your problem with the following LINQPad query against Northwind:
Employees.Where(e => e.EmployeeID == -999).Sum(e => e.EmployeeID)
There are two issues here:
- `Sum()` is overloaded
- LINQ to SQL follows SQL semantics, not C# semantics.
In SQL, `SUM(no rows)` returns `null`, not zero. However, the type inference for your query gives you `decimal` as the type parameter, instead of `decimal?`. The fix is to help type inference select the correct type, i.e.:
Employees.Where(e => e.EmployeeID == -999).Sum(e => (int?)e.EmployeeID)
Now the correct `Sum()` overload will be used.
Problem
I have a Linq collection of `Things`, where `Thing` has an `Amount` (decimal) property. I'm trying to do an aggregate on this for a certain subset of Things: ``` var total = myThings.Sum(t => t.Amount); ``` and that works nicely. But then I added a condition that left me with no Things in the result: ``` var total = myThings.Where(t => t.OtherProperty == 123).Sum(t => t.Amount); ``` And instead of getting total = 0 or null, I get an error: System.InvalidOperationException: The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type. That is really nasty, because I didn't expect that behavior. I would have expected total to be zero, maybe null - but certainly not to throw an exception! What am I doing wrong? What's the workaround/fix? EDIT - example Thanks to all for your comments. Here's some code, copied and pasted (not simplified). It's LinqToSql (perhaps that's why you couldn't reproduce my problem): ``` var claims = Claim.Where(cl => cl.ID < 0); var count = claims.Count(); // count=0 var sum = claims.Sum(cl => cl.ClaimedAmount); // throws exception ```