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'a été trouvé avec une exception:
The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type.
Je suppose que c'est parce que sum renvoie un int et non un int nullable, donnant à sum un int? en tant qu'entrée, donnez la même erreur, probablement parce que sum ne fonctionne que sur les 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, et alors ...
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 voulez utiliser la forme sumable de Sum, essayez donc de convertir votre valeur en une valeur 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:
En supposant que "v.Points" soit un nombre décimal, utilisez simplement les éléments suivants:
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 décimale nullabe, vous pouvez également utiliser la méthode Linq To Objects avec la méthode ToList ().
LinqToObjects La somme de la collection vide est 0, la somme LinqToSql de la collection vide est null.
Essayez de vérifier ceci:
var count = db.Cart.Where(c => c.UserName == "Name").Sum(c => (int?)c.Count) ?? 0;
Ainsi, la racine du problème est que la requête SQL ressemble à ceci:
SELECT SUM([Votes].[Value])
FROM [dbo].[Votes] AS [Votes]
WHERE 1 = [Votes].[UserId]
renvoie NULL
Une solution de contournement simple mais efficace consisterait à ne faire la somme que des votes où Points.Count> 0, de sorte que vous n'ayez jamais 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 ajouter une autre méthode dans le mélange :)
Where(q=> q.ItemId == b.ItemId && b.Points.HasValue).Sum(q=>q.Points.Value)
J'avais un scénario similaire mais je ne comparais pas un champ supplémentaire lors de la somme ...
Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);
Assuming Points est une liste de Int32, que diriez-vous de quelque chose comme:
var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)
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.
J'ai eu le même problème. Résolu avec l'union de liste vide:
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()
}
Dans le cas où "Points" est un entier, cela devrait fonctionner.
Peut-être mettre cette requête dans try/catch..if "exception", alors il n'y avait pas de votes
Semblable aux réponses précédentes, mais vous pouvez également convertir le résultat de la somme 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 il a le même effet que le casting dans cette réponse .
(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.
Je pensais lancer une autre solution. J'ai eu un problème similaire et voici comment j'ai fini par le résoudre:
Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)
J'avais un problème similaire et j'ai trouvé la solution qui consiste à récupérer tout ce que j'essayais de récupérer dans la base de données, à compter dessus et à ne payer que la somme restante. N'a pas pu faire fonctionner le casting pour une raison quelconque, donc l'affiche 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 ensuite, vérifiez si vous avez des résultats afin de ne pas obtenir la valeur null.
If (Votes.Count > 0) Then
Points = Votes.Sum(Function(v) v.Points)
End If