Hay un tipo de entidad llamada producto que es generado por el marco de la entidad. He escrito esta consulta
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
El siguiente código arroja el siguiente error:
"La entidad o tipo complejo Shop.Product no se puede construir en una consulta LINQ to Entities"
var products = productRepository.GetProducts(1).Tolist();
Pero cuando lo uso en select p
lugar de select new Product { Name = p.Name};
funciona correctamente.
¿Cómo puedo preformar una sección de selección personalizada?
c#
entity-framework
Ghooti Farangi
fuente
fuente
Respuestas:
No puede (y no debería poder) proyectar en una entidad asignada. Sin embargo, puede proyectar en un tipo anónimo o en un DTO :
Y su método devolverá una Lista de DTO.
fuente
Puede proyectar en tipo anónimo, y luego de él a tipo de modelo
Editar : Voy a ser un poco más específico ya que esta pregunta llamó mucho la atención.
No puede proyectar directamente en el tipo de modelo (restricción de EF), por lo que no hay forma de evitarlo. La única forma es proyectar en tipo anónimo (primera iteración), y luego modelar el tipo (segunda iteración).
Tenga en cuenta también que cuando carga entidades parcialmente de esta manera, no se pueden actualizar, por lo que deben permanecer separadas, tal como están.
Nunca entendí completamente por qué esto no es posible, y las respuestas en este hilo no dan fuertes razones en su contra (principalmente hablando de datos parcialmente cargados). Es correcto que en el estado de carga parcial la entidad no se pueda actualizar, pero luego, esta entidad se desconectaría, por lo que no serían posibles los intentos accidentales de salvarlos.
Considere el método que utilicé anteriormente: todavía tenemos una entidad modelo parcialmente cargada como resultado. Esta entidad está separada.
Considere este posible código (deseo de existir):
Esto también podría dar como resultado una lista de entidades separadas, por lo que no necesitaríamos hacer dos iteraciones. Un compilador sería inteligente al ver que se ha utilizado AsNoTracking (), lo que dará como resultado entidades separadas, por lo que podría permitirnos hacer esto. Sin embargo, si se omitió AsNoTracking (), podría lanzar la misma excepción que está lanzando ahora, para advertirnos que necesitamos ser lo suficientemente específicos sobre el resultado que queremos.
fuente
Hay otra forma en que encontré que funciona, tienes que construir una clase que se derive de tu clase de Producto y usarla. Por ejemplo:
No estoy seguro si esto está "permitido", pero funciona.
fuente
Aquí hay una manera de hacer esto sin declarar una clase adicional:
Sin embargo, esto solo se debe usar si desea combinar varias entidades en una sola entidad. La funcionalidad anterior (mapeo simple de producto a producto) se realiza así:
fuente
Otra forma simple :)
fuente
.ToList
consulta, se ejecuta y extrae datos del servidor, ¿cuál es el punto para hacerlo nuevamenteAsQueryable
?Puede usar esto y debería estar funcionando -> Debe usarlo
toList
antes de hacer la nueva lista usando select:fuente
En respuesta a la otra pregunta que se marcó como duplicado ( ver aquí ), descubrí una solución rápida y fácil basada en la respuesta de Soren:
Nota: Esta solución solo funciona si tiene una propiedad de navegación (clave externa) en la clase Tarea (aquí llamada 'Incidente'). Si no tiene eso, puede usar una de las otras soluciones publicadas con "AsQueryable ()".
fuente
Puede resolver esto utilizando Objetos de transferencia de datos (DTO).
Estos son un poco como los modelos de vista en los que coloca las propiedades que necesita y puede asignarlos manualmente en su controlador o mediante el uso de soluciones de terceros como AutoMapper.
Con DTO's puedes:
He estado aprendiendo esto en la escuela este año y es una herramienta muy útil.
fuente
Si está utilizando Entity Framework, intente eliminar la propiedad de DbContext que usa su modelo complejo como Entity. Tuve el mismo problema al mapear varios modelos en un modelo de vista llamado Entity
Eliminar la entrada de DbContext corrigió mi error.
fuente
si está ejecutando
Linq to Entity
no puede usar elClassType
connew
en elselect
cierre de la consultaonly anonymous types are allowed (new without type)
mira este fragmento de mi proyecto
de usted agregó el
new keyword
cierre en Seleccionar incluso en elcomplex properties
obtendrá este errorporque se transformará en una instrucción sql y se ejecutará en SqlServer
así que cuando puedo usar
new with types
enselect
el cierre?puedes usarlo si estás lidiando con
LINQ to Object (in memory collection)
después de ejecutar
ToList
en la consulta se convirtióin memory collection
para que podamos usarnew ClassTypes
en selectfuente
En muchos casos, la transformación no es necesaria. Piense por la razón por la que desea escribir la lista, y evalúe si solo desea los datos, por ejemplo, en un servicio web o para mostrarlos. No importa el tipo. Solo necesita saber cómo leerlo y verificar que sea idéntico a las propiedades definidas en el tipo anónimo que definió. Ese es el escenario óptimo, porque algo no necesita todos los campos de una entidad, y esa es la razón por la que existe el tipo anónimo.
Una manera simple es hacer esto:
fuente
No le permitirá volver a mapear en Producto ya que esa es su tabla que está consultando. Necesita una función anónima, luego puede agregarla a un ViewModel y agregar cada ViewModel a un
List<MyViewModel>
y devolverlos. Es una ligera digresión, pero incluyo advertencias sobre el manejo de fechas anulables porque es un problema difícil de manejar, en caso de que tenga alguna. Así es como lo manejé.Espero que tengas un
ProductViewModel
:Tengo un marco de inyección / repositorio de dependencia donde llamo a una función para tomar mis datos. Usando su publicación como ejemplo, en su llamada a la función Controlador, se vería así:
En la clase de repositorio:
De vuelta en el controlador, haces:
fuente
solo agregue AsEnumerable ():
fuente
Puede agregar AsEnumerable a su colección de la siguiente manera:
fuente