views:

3237

answers:

7
from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points).Sum()
}

I got this query, however it fails if no vots are found with "The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type.".

I assume its because sum returns an int and not a nullable int, giving sum a int? as input only give the same error, probably cause sum only workes on ints.

Any good workaround for this?

A: 

May be to put this query into try/catch..if "exception", then there were no votes found

nihi_l_ist
That won't help, that discards all items if one don't have votes. Its expected that some items never will get votes.
AndreasN
And besides, it's just a very bad solution to throw exceptions for this.
Razzie
got it :) thank you both for the comments
nihi_l_ist
+3  A: 
from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points ?? 0).Sum() 
}

EDIT - ok what about this... (Shooting again since I don't know your model...):

from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId)
              .Sum(v => v.Points) 
}
Rashack
Why doesn't it compile?
Dave Van den Eynde
sorry wrong copy paste there. It won't compile because Sum() returns an int. And the ?? operator don't work on non-nullable types.
AndreasN
I am just shooting here - I assume that sum of empty collection should be 0. So the issue might be that v.Points is nullable?
Rashack
So v.Points is a sequence of some sort?
Dave Van den Eynde
This answer works, but it doesn't explain -why- yours didn't work. See http://weblogs.asp.net/zeeshanhirani/archive/2008/07/15/applying-aggregates-to-empty-collections-causes-exception-in-linq-to-sql.aspx or look at my answer below...
Scott Stafford
+1  A: 

A simple but effective workaround would be to only sum the votes where Points.Count > 0, so you never have null values:

from i in Db.Items
select new VotedItem
{    
  ItemId = i.ItemId,
  Points = (from v in Db.Votes
            where b.ItemId == v.ItemId &&
            v.Points.Count > 0
            select v.Points).Sum()
}
Razzie
A: 

Is this a valid query? I thought that

where b.ItemId == v.ItemId

should have been

where i.ItemId == v.ItemId
daanish.rumani
A: 
        (from i in Db.Items
         where (from v in Db.Votes
                where i.ItemId == v.ItemId
                select v.Points).Count() > 0
         select new VotedItem
         {
             ItemId = i.ItemId,
             Points = (from v in Db.Items
                       where i.ItemId == v.ItemId
                       select v.Points).Sum()
         }).Union(from i in Db.Items
                  where (from v in Db.Votes
                         where i.ItemId == v.ItemId
                         select v.Points).Count() == 0
                  select new VotedItem
                  {
                      ItemId = i.ItemId,
                      Points = 0
                  }).OrderBy(i => i.Points);

This works, but isn't very pretty or readable.

AndreasN
In this case, shouldn't Rashack's answer work for you? I take it you want to get all items with corresponding number of votes, and if the votecount in the database is null (DBNull), then set Points to 0.
Razzie
+6  A: 

You want to use the nullable form of Sum, so try casting your value to a nullable:

from i in Db.Items
select new VotedItem
{
    ItemId = i.ItemId,
    Points = (from v in Db.Votes
              where b.ItemId == v.ItemId
              select v.Points).Sum(r => (decimal?) r.Points)
}

Your issue is discussed here in more detail:

http://weblogs.asp.net/zeeshanhirani/archive/2008/07/15/applying-aggregates-to-empty-collections-causes-exception-in-linq-to-sql.aspx

Scott Stafford
A: 

If you don't like casting to nullabe decimal you could also try using Linq To Objects with ToList() method,

LinqToObjects Sum of empty collection is 0, where LinqToSql Sum of empty collection is null.

Emir