Requête Linq avec sum 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() } 

J’ai eu cette requête, mais elle échoue si aucun vote n’est trouvé avec exception:

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

Je suppose que parce que la sum retourne un int et non un int nul, donnant une sum à int? comme l’entrée ne donne que la même erreur, probablement cause sum seulement fonctionne sur ints.

Une bonne solution pour cela?

 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 quoi à propos de ça … (Reprise du tournage car je ne connais pas votre modèle …):

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

Vous souhaitez utiliser la forme nullable de Sum, essayez donc de convertir votre valeur en 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) } 

Votre problème est discuté ici plus en détail:

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

En supposant que “v.Points” est une décimale, utilisez simplement ce qui suit:

 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 } 

Si vous n’aimez pas la conversion en nullabe decimal, vous pouvez également essayer d’utiliser la méthode Linq To Objects avec ToList (),

LinqToObjects La sum de la collection vide est 0, où LinqToSql Somme de la collection vide est nulle.

Essayez de vérifier ceci:

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

Donc, la racine du problème est que la requête SQL comme ceci:

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

renvoie NULL

Une solution simple mais efficace consisterait à additionner uniquement les votes où Points.Count> 0, afin de ne jamais avoir de valeurs nulles:

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

Juste pour append une autre méthode dans le mix 🙂

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

J’ai eu un scénario similaire mais je ne comparais pas un champ supplémentaire lors de la sum …

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

J’ai eu le même problème. Résolu avec une union de liste vide:

 List emptyPoints = new List() { 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() } 

Si “Points” est un nombre entier, cela devrait fonctionner.

Je pense que c’est le même cas. Je l’ai résolu. Ceci est ma solution:

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

J'espère que cette aide.

Peut-être pour mettre cette requête dans try / catch..si “exception”, alors aucun vote n’a été trouvé

En supposant que Points est une liste d’Int32, que diriez-vous de quelque chose comme:

 var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0) 
  (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); 

Cela fonctionne, mais n’est pas très joli ou lisible.

J’ai eu un problème similaire et j’ai trouvé la solution pour obtenir tout ce que j’essayais de sortir de la firebase database, faire un compte sur ceux-ci et seulement si j’avais quelque chose retourné faire une sum. Je n’ai pas réussi à convaincre les acteurs de travailler pour quelque raison que ce soit, en postant cela si quelqu’un d’autre avait des problèmes similaires.

par exemple

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

Et puis vérifiez si vous avez des résultats afin que vous n’obteniez pas de null.

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

Semblable aux réponses précédentes, mais vous pouvez également convertir le résultat de la sum entière en type Nullable.

 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 } 

On peut dire que cela correspond mieux à ce qui se passe réellement, mais cela a le même effet que la dissortingbution de cette réponse .

Je pensais lancer une autre solution. J’ai eu un problème similaire et c’est comme ça que j’ai fini par le résoudre:

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