Hay un tipo de entidad llamado Product 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 uso select p en lugar de select new Product { Name = p.Name}; funciona correctamente.
¿Cómo puedo realizar una sección de selección personalizada?
No puede (y no debería poder) proyectar en una entidad mapeada. Sin embargo, puede proyectar en un tipo anónimo o en un DTO :
public class ProductDTO { public string Name { get; set; } // Other field you may need from the Product entity }Y su método devolverá una Lista de DTO.
public List<ProductDTO> GetProducts(int categoryID) { return (from p in db.Products where p.CategoryID == categoryID select new ProductDTO { Name = p.Name }).ToList(); }Puede proyectar en tipo anónimo y luego de él al tipo de modelo
public IEnumerable<Product> GetProducts(int categoryID) { return (from p in Context.Set<Product>() where p.CategoryID == categoryID select new { Name = p.Name }).ToList() .Select(x => new Product { Name = x.Name }); }Editar : voy a ser un poco más específico ya que esta pregunta llamó mucho la atención.
No puede proyectar en el tipo de modelo directamente (restricción EF), por lo que no hay forma de evitar esto. La única forma es proyectar en tipo anónimo (primera iteración) y luego en tipo de modelo (segunda iteración).
También tenga en cuenta 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 razones sólidas en contra (principalmente hablando de datos parcialmente cargados). Es correcto que en el estado de carga parcial la entidad no se puede actualizar, pero entonces, esta entidad se desconectaría, por lo que no sería posible intentar guardarla accidentalmente.
Considere el método que usé anteriormente: todavía tenemos una entidad de modelo parcialmente cargada como resultado. Esta entidad está separada.
Considere este posible código (deseo de existir):
return (from p in Context.Set<Product>() where p.CategoryID == categoryID select new Product { Name = p.Name }).AsNoTracking().ToList();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 para 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 omitiera AsNoTracking(), podría lanzar la misma excepción que está lanzando ahora, para advertirnos que debemos ser lo suficientemente específicos sobre el resultado que queremos.
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:
public class PseudoProduct : Product { } public IQueryable<Product> GetProducts(int categoryID) { return from p in db.Products where p.CategoryID== categoryID select new PseudoProduct() { Name = p.Name}; }No estoy seguro si esto está "permitido", pero funciona.