sqlquery raw query fromsql framework efcore c# .net sql linq average

c# - fromsql - raw query linq



Método de extensión promedio en Linq para el valor predeterminado (3)

¿Alguien sabe cómo puedo establecer un valor predeterminado para un promedio? Tengo una línea como esta ...

dbPlugins = (from p in dbPlugins select new { Plugin = p, AvgScore = p.DbVersions.Average(x => x.DbRatings.Average(y => y.Score)) }) .OrderByDescending(x => x.AvgScore) .Select(x => x.Plugin).ToList();

que arroja un error porque no tengo calificaciones todavía. Si no tengo ninguno, deseo que el promedio sea predeterminado en 0. Pensaba que este debería ser un método de extensión donde podría especificar cuál debería ser el valor predeterminado.


Hay: DefaultIfEmpty .

No estoy seguro de cuáles son sus DbVersions y DbRatings y qué colección tiene exactamente cero elementos, pero esta es la idea:

var emptyCollection = new List<int>(); var average = emptyCollection.DefaultIfEmpty(0).Average();

Actualización: (repitiendo lo que se dice en los comentarios a continuación para aumentar la visibilidad)

Si necesita usar DefaultIfEmpty en una colección de tipo de clase, recuerde que puede cambiar la consulta LINQ al proyecto antes de agregar. Por ejemplo:

class Item { public int Value { get; set; } } var list = new List<Item>(); var avg = list.Average(item => item.Value);

Si no desea / no puede construir un Item predeterminado con un Value igual a 0, puede proyectar primero una colección de int s y luego proporcionar un valor predeterminado:

var avg = list.Select(item => item.Value).DefaultIfEmpty(0).Average();


Intenté algunas de esas respuestas, pero obtuve más excepciones por una razón u otra. esto terminó trabajando para mí. Estoy seguro de que el rendimiento es impresionante, pero lo revisaré más adelante.

var q1 = from v in db.DbVersions select new { VersionId = v.Id, AvgScore = v.DbRatings.Average(x => x.Score) as Nullable<double> }; var q2 = from p in dbPlugins select new { Plugin = p, AvgScore = q1.Where(x => p.DbVersions.Select(y => y.Id).Contains(x.VersionId)).Average(x => x.AvgScore) as Nullable<double> }; dbPlugins = q2.OrderByDescending(x => x.AvgScore).Select(x => x.Plugin).ToList();


No creo que haya una manera de seleccionar la opción predeterminada, pero ¿qué hay de esta consulta?

dbPlugins = (from p in dbPlugins select new { Plugin = p, AvgScore = p.DbVersions.Any(x => x.DbRatings) ? p.DbVersions.Average(x => x.DbRatings.Average(y => y.Score)) : 0 }) .OrderByDescending(x => x.AvgScore) .Select(x => x.Plugin).ToList();

Esencialmente igual que el tuyo, pero primero preguntamos si hay calificaciones antes de promediarlas. Si no, devolvemos 0.