Pregunta

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

Tengo esta consulta, sin embargo, falla si no hay votos se encontraron con una excepción:

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

Asumo que es porque suma devuelve un int y no un int anulable, dando una suma int? como entrada sólo dan el mismo error, probablemente causar suma única workes en enteros.

Cualquier buena solución para esto?

¿Fue útil?

Solución

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 - bien qué pasa con esto ... (toma de nuevo ya que no sé su 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) 
}

Otros consejos

Usted desea utilizar la forma anulable de Suma, así que trata de la emisión de su valor a un anulable:

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 tema se discute aquí en más detalle:

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

"Suponiendo v.Points" es un decimal sólo tiene que utilizar el 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
}

Si no te gusta la fundición hasta nullabe decimal también se podría tratar de usar LINQ to Objects con el método ToList (),

LinqToObjects Suma de colección vacía es 0, donde LinqToSql Suma de colección vacía es nulo.

Trate de comprobar esto:

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

Por lo tanto, la raíz del problema es que la consulta SQL como esto:

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

devuelve NULL

Una solución sencilla pero eficaz sería la única suma los votos donde Points.Count> 0, para que nunca tenga 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()
}

Sólo para añadir otro método en la mezcla:)

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

Yo tenía un escenario similar pero no estaba comparando un campo adicional al resumir ...

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

Si se asume Puntos es una lista de Int32, ¿qué tal algo como:

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

Yo tenía el mismo problema. Resuelto con la unión 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 número entero esto debería funcionar.

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 que esta ayuda.

        (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 bonita o legible.

Yo tenía un problema similar y se acercó con la solución de conseguir lo que yo estaba tratando de salir de la base de datos, hacer un recuento de los y sólo si tenía algo regresado hacer una suma. No fue capaz de conseguir el modelo de trabajo por alguna razón lo que la publicación de este si alguien más tenía problemas similares.

por ejemplo.

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

Y a continuación, comprobar para ver si tienes ningún resultado para que no se les devuelve null.

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

Al igual que en las respuestas anteriores, pero también se puede emitir el resultado de la suma total al tipo anulable.

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 mejor se adapte a lo que realmente está pasando, pero tiene el mismo efecto que el reparto en esta respuesta .

Pensaba que iba a tirar otra solución por ahí. Tenía un problema similar y así es como terminé resolverlo:

Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top