remarks example español c# linq-to-entities

example - params comments c#



Solo los constructores y los inicializadores sin parámetros son compatibles con LINQ para Entidades (12)

Además de los métodos antes mencionados, también puede analizarlos como una colección de Enumerable, como esta:

(from x in table .... ).AsEnumerable() .Select(x => ...)

Esto también tiene el beneficio adicional de facilitar la vida al construir un objeto anónimo, como este:

(from x in tableName select x.obj) .Where(x => x.id != null) .AsEnumerable() .Select(x => new { objectOne = new ObjectName(x.property1, x.property2), parentObj = x }) .ToList();

Recordando, sin embargo, que analizar una colección como Enumerable lo lleva a la memoria, ¡así que puede requerir muchos recursos! La precaución se debe utilizar aquí.

Tengo este error en esta expresión linq:

var naleznosci = (from nalTmp in db.Naleznosci where nalTmp.idDziecko == idDziec select new Payments ( nalTmp.Dziecko.Imie, nalTmp.Dziecko.Nazwisko, nalTmp.Miesiace.Nazwa, nalTmp.Kwota, nalTmp.RodzajeOplat.NazwaRodzajuOplaty, nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty, nalTmp.DataRozliczenia, nalTmp.TerminPlatnosci )).ToList();

Alguna idea de como resolver este problema? Lo intento con cualquier combinación de expresión ...: /


Además, si desea utilizar un constructor con varios objetos para inicializar, es posible que obtenga un error si Linq no devuelve ningún valor.

Entonces, quizás quieras hacer algo como esto:

(from x in table_1 join y in table_2 on x.id equals y.id select new { val1 = x, val2 = y }) .DefaultIfEmpty() .ToList() .Select(a => new Val_Constructor(a.val1 != null ? a.val1 : new Val_1_Constructor(), a.val2 != null ? a.val2 : new Val_2_Constructor())) .ToList();


Habiendo encontrado este error yo mismo, pensé que agregaría que si el tipo de Payment es una struct , también encontraría el mismo error porque los tipos de struct no admiten constructores sin parámetros.

En ese caso, convertir el Payment en una clase y usar la sintaxis del inicializador de objetos resolverá el problema.


Perdón por llegar tarde a la fiesta, pero después de encontrar this , pensé que debería compartirse ya que es la implementación más limpia, rápida y que ahorra memoria que pude encontrar.

Adaptado a tu ejemplo, escribirías:

public static IQueryable<Payments> ToPayments(this IQueryable<Naleznosci> source) { Expression<Func<Naleznosci, Payments>> createPayments = naleznosci => new Payments { Imie = source.Dziecko.Imie, Nazwisko = source.Dziecko.Nazwisko, Nazwa= source.Miesiace.Nazwa, Kwota = source.Kwota, NazwaRodzajuOplaty = source.RodzajeOplat.NazwaRodzajuOplaty, NazwaTypuOplaty = source.RodzajeOplat.TypyOplat.NazwaTypuOplaty, DataRozliczenia = source.DataRozliczenia, TerminPlatnosci = source.TerminPlatnosci, }; return source.Select(createPayments); }

Las grandes ventajas aquí (como señaló Damien Guard en los comentarios en el enlace) son:

  • Le impide utilizar el patrón de inicialización en cada aparición.
  • Uso a través de var foo = createPayments(bar); así como el uso a través de myIQueryable.ToPayments () posible.

Primero evitaría la solución con

from .... select new Payments { Imie = nalTmp.Dziecko.Imie, .... }

Esto requiere un constructor vacío e ignora la encapsulación, por lo que está diciendo que Pagos () nuevos es un pago válido sin ningún dato, sino que el objeto debe tener al menos un valor y probablemente otros campos obligatorios según su dominio.

Es mejor tener un constructor para los campos requeridos, pero solo traer los datos necesarios:

from .... select new { Imie = nalTmp.Dziecko.Imie, Nazwisko = nalTmp.Dziecko.Nazwisko .... } .ToList() // Here comes transfer to LINQ to Collections. .Select(nalImp => new Payments ( nalTmp.Imie,//assume this is a required field ........... ) { Nazwisko = nalTmp.Nazwisko //optional field }) .ToList();


Puede intentar hacer lo mismo, pero usando los métodos de extensión. ¿Cuál es el proveedor del uso de la base de datos?

var naleznosci = db.Naleznosci .Where<TSource>(nalTmp => nalTmp.idDziecko == idDziec) .Select<TSource, TResult>( delegate(TSource nalTmp) { return new Payments ( nalTmp.Dziecko.Imie, nalTmp.Dziecko.Nazwisko, nalTmp.Miesiace.Nazwa, nalTmp.Kwota, nalTmp.RodzajeOplat.NazwaRodzajuOplaty, nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty, nalTmp.DataRozliczenia, nalTmp.TerminPlatnosci ); }) .ToList();


Si aún desea utilizar su constructor para la inicialización y no propiedades (a veces este comportamiento se desea para propósitos de inicialización), enumere la consulta llamando a ToList() o ToArray() , y luego use Select(…) . Por lo tanto, utilizará LINQ to Collections y esa limitación de no poder llamar al constructor con los parámetros en Select(…) se desvanecerá.

Por lo tanto, su código debería verse más o menos así:

var naleznosci = db.Naleznosci .Where(nalTmp => nalTmp.idDziecko == idDziec) .ToList() // Here comes transfer to LINQ to Collections. .Select(nalImp => new Payments ( nalTmp.Dziecko.Imie, nalTmp.Dziecko.Nazwisko, nalTmp.Miesiace.Nazwa, nalTmp.Kwota, nalTmp.RodzajeOplat.NazwaRodzajuOplaty, nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty, nalTmp.DataRozliczenia, nalTmp.TerminPlatnosci )) .ToList();


Si eres como yo y no quieres tener que rellenar tus propiedades para cada consulta que estás creando, hay otra manera de resolver este problema.

var query = from orderDetail in context.OrderDetails join order in context.Orders on order.OrderId equals orderDetail.orderId select new { order, orderDetail };

En este punto, tiene un IQueryable que contiene un objeto anónimo. Si desea rellenar su objeto personalizado con un constructor, simplemente puede hacer algo como esto:

return query.ToList().Select(r => new OrderDetails(r.order, r.orderDetail));

Ahora su objeto personalizado (que toma dos objetos como parámetro) puede poblar sus propiedades según sea necesario.


Solo ToList () el DbSet antes de la instrucción Select ... el DbSet real se guarda como una consulta, aún no se ha cumplido. después de llamar a ToList () Estás jugando con objetos, y allí puedes usar un constructor no predeterminado en la consulta. no es la manera más eficiente de usar el tiempo, pero es una opción en juegos pequeños.


Tuve el mismo problema hoy y mi solución fue similar a la que Yoda enumeró, sin embargo, solo funciona con sintaxis fluida.

Adaptando mi solución a su código: agregué el siguiente método estático a la clase de objeto

/// <summary> /// use this instead of a parameritized constructor when you need support /// for LINQ to entities (fluent syntax only) /// </summary> /// <returns></returns> public static Func<Naleznosci, Payments> Initializer() { return n => new Payments { Imie = n.Dziecko.Imie, Nazwisko = n.Dziecko.Nazwisko, Nazwa = n.Miesiace.Nazwa, Kwota = n.Kwota, NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty, NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty, DataRozliczenia = n.DataRozliczenia, TerminPlatnosc = n.TerminPlatnosci }; }

y luego actualizó la consulta base a lo siguiente:

var naleznosci = (from nalTmp in db.Naleznosci where nalTmp.idDziecko == idDziec select new Payments.Initializer());

Esto es lógicamente equivalente a la solución de James Manning con la ventaja de impulsar la saturación de la inicialización de miembros al Objeto de Transferencia de Clase / Datos

Nota: Originalmente estaba usando nombres más descriptivos que "Inicializador" pero después de revisar cómo lo estaba usando, encontré que "Initilizer" era suficiente (al menos para mis propósitos).

Nota final:
Después de pensar en esta solución, al principio pensé que sería simple compartir el mismo código y adaptarlo para trabajar con la sintaxis de Query. Ya no creo que ese sea el caso. Creo que si quieres poder utilizar este tipo de construcción de taquigrafía necesitarás un método para cada uno (consulta, fluidez) con fluidez como se describió anteriormente, que puede existir en la propia clase de objeto.

Para la sintaxis de consulta, se requeriría un método de extensión (o algún método fuera de la clase base utilizada). (dado que la sintaxis de la consulta quiere operar un IQueryable en lugar de T)

Aquí hay una muestra de lo que solía hacer para que finalmente funcionara la sintaxis de la consulta. (Yoda ya lo entendió, pero creo que el uso podría ser más claro porque al principio no lo entendí)

/// <summary> /// use this instead of a parameritized constructor when you need support /// for LINQ to entities (query syntax only) /// </summary> /// <returns></returns> public static IQueryable<Payments> Initializer(this IQueryable<Naleznosci> source) { return source.Select( n => new Payments { Imie = n.Dziecko.Imie, Nazwisko = n.Dziecko.Nazwisko, Nazwa = n.Miesiace.Nazwa, Kwota = n.Kwota, NazwaRodzajuOplaty = n.RodzajeOplat.NazwaRodzajuOplaty, NazwaTypuOplaty = n.RodzajeOplat.TypyOplat.NazwaTypuOplaty, DataRozliczenia = n.DataRozliczenia, TerminPlatnosc = n.TerminPlatnosci }; }

y el uso

var naleznosci = (from nalTmp in db.Naleznosci where nalTmp.idDziecko == idDziec select nalTmp).Initializer().ToList();


sin más información sobre ''Pagos'' esto no ayuda mucho, pero suponiendo que desea crear un objeto de Pagos y establecer algunas de sus propiedades en función de los valores de columna:

var naleznosci = (from nalTmp in db.Naleznosci where nalTmp.idDziecko == idDziec select new Payments { Imie = nalTmp.Dziecko.Imie, Nazwisko = nalTmp.Dziecko.Nazwisko, Nazwa= nalTmp.Miesiace.Nazwa, Kwota = nalTmp.Kwota, NazwaRodzajuOplaty = nalTmp.RodzajeOplat.NazwaRodzajuOplaty, NazwaTypuOplaty = nalTmp.RodzajeOplat.TypyOplat.NazwaTypuOplaty, DataRozliczenia = nalTmp.DataRozliczenia, TerminPlatnosci = nalTmp.TerminPlatnosci, }).ToList();


yeh, pruébalo así ...

var naleznosci = (from nalTmp in db.Naleznosci where nalTmp.idDziecko == idDziec select new Payments() { Dziecko.Imie, Dziecko.Nazwisko, Miesiace.Nazwa, Kwota, RodzajeOplat.NazwaRodzajuOplaty, RodzajeOplat.TypyOplat.NazwaTypuOplaty, DataRozliczenia, TerminPlatnosci }).ToList();

esto actualizará su objeto Payment utilizando un constructor sin parámetros, y luego inicializará las propiedades que se enumeran dentro de las llaves { }