it-swarm.com.de

Linq-Abfrage mit nullfähiger Summe

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()
}

Ich habe diese Abfrage erhalten, die jedoch fehlschlägt, wenn keine Stimmen mit Ausnahme gefunden werden:

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

Ich gehe davon aus, dass weil die Summe ein int und kein nullbares int zurückgibt, was der Summe ein int ergibt. da die eingabe nur den gleichen fehler ergibt, wirkt sich die summe nur auf ints aus.

Gibt es eine gute Lösung für dieses Problem?

67
AndreasN
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() 
}

BEARBEITEN - ok was ist damit ... (Nochmal schießen, da ich dein Modell nicht kenne ...):

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) 
}
22
Rashack

Sie möchten die nullfähige Form von Sum verwenden. Versuchen Sie daher, Ihren Wert in eine nullfähige umzuwandeln:

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)
}

Ihr Problem wird hier ausführlicher besprochen: 

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

73
Scott Stafford

Angenommen, "v.Points" ist eine Dezimalzahl, verwenden Sie einfach Folgendes:

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

Wenn Sie keine Umwandlung in nullabe decimal möchten, können Sie auch die Linq To Objects-Methode mit ToList () verwenden.

LinqToObjects Summe der leeren Auflistung ist 0, wobei LinqToSql Summe der leeren Auflistung null ist.

11
Emir

Versuchen Sie dies herauszufinden:

var count = db.Cart.Where(c => c.UserName == "Name").Sum(c => (int?)c.Count) ?? 0;

Die Ursache des Problems ist also, dass die SQL-Abfrage folgendermaßen lautet:

SELECT SUM([Votes].[Value])
FROM [dbo].[Votes] AS [Votes]
WHERE 1 = [Votes].[UserId] 

gibt NULL zurück

10
Pavel Shkleinik

Eine einfache, aber effektive Problemumgehung wäre, nur die Stimmen zu summieren, bei denen Punkte.Zahl> 0 ist, sodass Sie niemals Nullwerte haben:

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()
}
5
Razzie

Nur um eine weitere Methode in die Mischung einzufügen :)

Where(q=> q.ItemId == b.ItemId && b.Points.HasValue).Sum(q=>q.Points.Value)

Ich hatte ein ähnliches Szenario, habe aber beim Summieren kein zusätzliches Feld verglichen ...

Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);
4
Phil

Das Annehmen von Punkten ist eine Liste von Int32.

var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)
3
ProfNimrod

Ich denke, das ist der gleiche Fall ... Ich habe es gelöst. Das ist meine Lösung:

var x = (from a in this.db.Pohybs
                 let sum = (from p in a.Pohybs
                            where p.PohybTyp.Vydej == true
                            select p.PocetJednotek).Sum()
                 where a.IDDil == IDDil && a.PohybTyp.Vydej == false
                 && ( ((int?)sum??0) < a.PocetJednotek)
                 select a);

Ich hoffe diese Hilfe.

2
Pepa

Ich hatte das gleiche Problem. Mit leerer Listenvereinigung gelöst:

List<int> emptyPoints = new List<int>() { 0 };

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).Union(emptyPoints).Sum()
}

Wenn "Punkte" eine Ganzzahl ist, sollte dies funktionieren.

2
Alex

Diese Abfrage könnte in try/catch..if gesetzt sein, wenn keine Ausnahme gefunden wurde

1
0x49D1

Ähnlich wie die vorherigen Antworten, Sie können aber auch das Ergebnis der gesamten Summe in den Typ mit Nullwert umwandeln.

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

Das passt wohl besser zu dem, was wirklich vor sich geht, aber es hat den gleichen Effekt wie der Cast in diese Antwort .

0
OlduwanSteve
        (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);

Das funktioniert, ist aber nicht sehr hübsch oder lesbar.

0
AndreasN

Ich dachte, ich würde eine andere Lösung da draußen werfen. Ich hatte ein ähnliches Problem und so habe ich das Problem gelöst:

Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)
0
Jeff

Ich hatte ein ähnliches Problem und kam zu der Lösung, alles, was ich versuchte, aus der Datenbank zu bekommen, zu zählen, auf diese zu zählen und nur dann, wenn ich etwas zurückbekommen hatte, eine Summe zu machen. War nicht in der Lage, die Besetzung aus irgendeinem Grund zum Laufen zu bringen, so dass dies veröffentlicht wird, wenn andere Personen ähnliche Probleme hatten.

z.B.

Votes = (from v in Db.Votes
          where b.ItemId = v.ItemId
          select v)

Überprüfen Sie dann, ob Sie Ergebnisse erhalten, sodass keine Nullwerte zurückgegeben werden.

If (Votes.Count > 0) Then
    Points = Votes.Sum(Function(v) v.Points)
End If
0
tcmorris