visual una propiedades objeto metodos listas lista instanciar inicializar hacer declarar clase c# linq linq-to-entities

c# - una - Solo se admiten constructores sin parámetros e inicializadores en LINQ para el mensaje de Entidades



metodos de listas en c# (4)

Tengo un método que devuelve datos de un modelo EF.

Recibo el mensaje anterior, pero no puedo ver cómo evitar el problema.

public static IEnumerable<FundedCount> GetFundedCount() { var today = DateTime.Now; var daysInMonth = DateTime.DaysInMonth(today.Year, today.Month); var day1 = DateTime.Now.AddDays(-1); var day31 = DateTime.Now.AddDays(-31); using (var uow = new UnitOfWork(ConnectionString.PaydayLenders)) { var r = new Repository<MatchHistory>(uow.Context); return r.Find() .Where(x => x.AppliedOn >= day1 && x.AppliedOn <= day31 && x.ResultTypeId == (int)MatchResultType.Accepted) .GroupBy(x => new { x.BuyerId, x.AppliedOn }) .Select(x => new FundedCount( x.Key.BuyerId, x.Count() / 30 * daysInMonth)) .ToList(); } }

FundedCount no es una entidad EF, MatchHistory es, por lo que no puedo entender por qué se queja.

Todos los consejos apreciados.


El mensaje es claro: linq para entidades no admite objetos sin un ctor sin parámetros.

Asi que

Solución 1

enumerar antes (o usar un tipo anónimo intermedio y enumerar en ese)

.ToList() .Select(x => new FundedCount( x.Key.BuyerId, x.Count() / 30 * daysInMonth)) .ToList();

Solución 2

agregue un ctor sin parámetros a su clase de FundedCount (si es posible)

public FundedCount() {}

y use

.Select(x => new FundedCount{ <Property1> = x.Key.BuyerId, <Property2> = x.Count() / 30 * daysInMonth }) .ToList();


La razón por la que se queja es porque no sabe cómo traducir su Select() a una expresión SQL. Si necesita realizar una transformación de datos a un POCO que no sea una entidad, primero debe obtener los datos relevantes de EF y luego transformarlos en el POCO.

En su caso, debería ser tan simple como llamar a ToList() antes:

return r.Find() .Where(x => x.AppliedOn >= day1 && x.AppliedOn <= day31 && x.ResultTypeId == (int)MatchResultType.Accepted) .GroupBy(x => new { x.BuyerId, x.AppliedOn }) .ToList() // this causes the query to execute .Select(x => new FundedCount(x.Key.BuyerId, x.Count() / 30 * daysInMonth));

Sin embargo, tenga cuidado con esto y asegúrese de limitar el tamaño del conjunto de datos devuelto por ToList() tanto como sea posible para no intentar cargar una tabla completa en la memoria.


Se está quejando porque no puede convertir las referencias a FundedCount en declaraciones SQL.

Todos los proveedores de LINQ convierten las declaraciones y expresiones de LINQ en operaciones que su objetivo puede comprender. LINQ a SQL y LINQ a EF convertirán LINQ a SQL, PLINQ lo convertirá en Tareas y operaciones paralelas, LINQ a Sharepoint lo convertirá a CAML, etc.

Lo que sucede si no pueden hacer la conversión, depende del proveedor. Algunos proveedores devolverán resultados intermedios y convertirán el resto de la consulta en una consulta de LINQ to Objects. Otros simplemente fallarán con un mensaje de error.

Fallar con un mensaje es en realidad una mejor opción cuando se habla con una base de datos. De lo contrario, el servidor tendría que devolver todas las columnas al cliente cuando solo 1 o 2 serían realmente necesarias.

En su caso, debe modificar su selección para devolver un tipo anónimo con los datos que desea, llame a ToList () y LUEGO cree los objetos FundedCount, por ejemplo:

.Select( x=> new {Id=x.Key.BuyerId,Count=x.Count()/30 * daysInMonth) .ToList() .Select(y => new FundedCount(y.Id,y.Count)) .ToList();

La primera ToList () forzará la generación de la declaración SQL y ejecutará la consulta que devolverá solo los datos que necesita. El resto de la consulta es en realidad Linq to Objects y obtendrá los datos y creará los objetos finales.


Tuve la misma excepción en GroupBy. Descubrí que la excepción "Solo los constructores sin parámetros y los inicializadores son compatibles con LINQ para Entidades" no es una descripción 100% precisa.

Tuve un GroupBy () en mi "consulta de Linq a EntityFramework" que usaba una estructura como clave en GroupBy. Eso no funcionó. Cuando cambié esa estructura a la clase normal, todo funcionó bien.

Muestra de código

var affectedRegistrationsGrouped = await db.Registrations .Include(r => r.Person) .Where(r => //whatever ) .GroupBy(r => new GroupByKey { EventId = r.EventId, SportId = r.SportId.Value }) .ToListAsync(); ... ... // this does not work private struct GroupByKey() {...} // this works fine private class GroupByKey() {...}