Consulta Linq con suma 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()
}

Recibí esta consulta, sin embargo, falla si no se encuentran votos con la excepción:

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

Asumo su porque sum devuelve un int y no un int nullable, dando sum un int? como la entrada solo da el mismo error, probablemente causa que la suma solo funcione en ints.

¿Alguna buena solución para esto?

Author: Rui Jarimba, 2009-03-30

15 answers

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 qué pasa con esto... (Disparando de nuevo ya que no conozco a 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) 
}
 21
Author: Rashack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-30 10:36:08

Desea usar la forma nullable de Suma, así que intente convertir su valor en una 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)
}

Su problema se discute aquí con más detalle:

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

 72
Author: Scott Stafford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-09 21:50:27

Suponiendo que "v. Puntos" es un decimal, simplemente 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
}
 19
Author: Jeroen Bernsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-13 15:58:51

Si no te gusta hacer casting a nullabe decimal también puedes intentar usar Linq A Objetos con el método ToList (),

La suma de LinqToObjects de la colección vacía es 0, donde la Suma de LinqToSql de la colección vacía es null.

 11
Author: Emir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-15 22:22:30

Intenta comprobar esto:

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

Entonces, la raíz del problema es que la consulta SQL como esta:

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

Devuelve NULL

 10
Author: Pavel Shkleinik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-23 11:38:54

Una solución simple pero efectiva sería sumar solo los votos donde los puntos.Count > 0, por lo que nunca tiene 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()
}
 5
Author: Razzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-30 08:53:11

Solo para añadir otro método a la mezcla:)

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

Tuve un escenario similar, pero no estaba comparando un campo adicional al sumar...

Where(q => q.FinalValue.HasValue).Sum(q=>q.FinalValue.Value);
 4
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-05 15:53:47

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

 2
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 14:46:00

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 esto ayude.

 2
Author: Pepa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-28 09:11:04

Suponiendo que los puntos son una Lista de Int32, ¿qué tal algo como:

var sum = Points.DefaultIfEmpty().Sum(c => (Int32)c ?? 0)
 2
Author: ProfNimrod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-21 21:22:11

Puede ser poner esta consulta en try/catch..si "excepción", entonces no se encontraron votos

 1
Author: 0x49D1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-30 08:45:36
        (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 o legible.

 0
Author: AndreasN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-30 10:24:17

Tuve un problema similar y se me ocurrió la solución de obtener lo que estaba tratando de sacar de la base de datos, hacer un recuento de ellos y luego solo si tenía algo devuelto hacer una suma. No fue capaz de conseguir el reparto de trabajo por alguna razón para publicar esto si alguien más tenía problemas similares.

Por ejemplo

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 null.

If (Votes.Count > 0) Then
    Points = Votes.Sum(Function(v) v.Points)
End If
 0
Author: tcmorris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 16:00:40

Similar a las respuestas anteriores, pero también puede convertir el resultado de la suma completa al tipo 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
}

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.

 0
Author: OlduwanSteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:59

Pensé en lanzar otra solución por ahí. Tuve un problema similar y así es como terminé solucionándolo:

Where(a => a.ItemId == b.ItemId && !b.IsPointsNull()).Sum(b => b.Points)
 0
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 19:07:33