c# - funcion - Consulta de Linq con suma anulable
suma linq c# (15)
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()
}
Recibí esta consulta, sin embargo, falla si no se encuentran votos con excepción:
The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type.
Supongo que es porque suma devuelve un int y no una int nullable, dando suma un int? como entrada solo da el mismo error, probablemente causa suma solo trabajos en ints.
¿Alguna buena solución para esto?
Asumir puntos es una lista de Int32, ¿qué tal algo así como:
var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)
Creo que este es el mismo caso. Lo resolví Esta es mi solución:
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);
Espero esta ayuda.
Desea utilizar la forma Nullable de Sum, así que intente convertir su valor en un valor nulo:
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)
}
Su problema se analiza aquí con más detalle:
Pensé que lanzaría otra solución por ahí. Tuve un problema similar y así es como terminé resolviéndolo:
Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)
Puede ser para poner esta consulta en try / catch..if "exception", luego no se encontraron votos
Si no te gusta transmitir a nullabe decimal, también puedes intentar usar el método Linq To Objects with ToList (),
LinqToObjects La suma de la colección vacía es 0, donde LinqToSql La suma de la colección vacía es nula.
Similar a las respuestas anteriores, pero también puede convertir el resultado de la suma total al tipo que admite nulos.
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
}
Podría decirse que esto se ajusta mejor a lo que realmente está sucediendo, pero tiene el mismo efecto que el elenco en esta respuesta .
Solo para agregar otro método a la mezcla :)
Where(q=> q.ItemId == b.ItemId && b.Points.HasValue).Sum(q=>q.Points.Value)
Tenía un escenario similar pero no estaba comparando un campo adicional al sumar ...
Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);
Suponiendo que "v.Points" es un decimal, solo use lo siguiente:
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
}
Trata de verificar esto:
var count = db.Cart.Where(c => c.UserName == "Name").Sum(c => (int?)c.Count) ?? 0;
Entonces, la raíz del problema es esa consulta SQL así:
SELECT SUM([Votes].[Value])
FROM [dbo].[Votes] AS [Votes]
WHERE 1 = [Votes].[UserId]
devuelve NULL
Tuve un problema similar y se me ocurrió la solución de obtener todo lo que estaba tratando de obtener de la base de datos, hacer un recuento de esos y solo si me devolvía algo, haga una suma. No fue posible hacer funcionar al elenco por algún motivo, por lo que se publicó esto si alguien más tenía problemas similares.
p.ej
Votes = (from v in Db.Votes
where b.ItemId = v.ItemId
select v)
Y luego verifique si tiene algún resultado para que no se devuelva nulo.
If (Votes.Count > 0) Then
Points = Votes.Sum(Function(v) v.Points)
End If
Una solución simple pero efectiva sería solo sumar los votos donde Points.Count> 0, por lo que nunca tendrá valores nulos:
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()
}
Yo tuve el mismo problema. Lo resolvió con la unión de la lista vacía:
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()
}
En el caso de "Puntos" es un número entero, esto debería funcionar.
(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);
Esto funciona, pero no es muy bonito ni legible.
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()
}
EDITAR - vale, ¿qué pasa con esto ... (Disparando de nuevo ya que no conozco tu modelo ...):
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)
}