2011-08-02 14 views
87

estoy recibiendo esta excepción:Sólo inicializadores, miembros de la entidad, y las propiedades de navegación entidad son compatibles

El miembro tipo especificado 'cargo' no se admite en LINQ a Entidades. Solo se admiten inicializadores, miembros de entidades y propiedades de navegación de entidades .

public ActionResult Index() 
    { 
     var debts = storeDB.Orders 
      .Where(o => o.Paid == false) 
      .OrderByDescending(o => o.DateCreated); 

     return View(debts); 
    } 

Mi clase Modelo

public partial class Order 
{ 
    public bool Paid { 
     get { 
      return TotalPaid >= Total; 
     } 
    } 

    public decimal TotalPaid { 
     get { 
      return Payments.Sum(p => p.Amount); 
     } 
    } 

Pagos es una tabla relacionada que contiene la cantidad de campo, La consulta funciona si quito la cláusula WHERE que muestra la información correcta sobre los pagos, alguna idea de lo que está mal con ¿el código?

Resuelto como la respuesta sugirió con:

public ActionResult Index() 
    { 
     var debts = storeDB.Orders 
      .OrderByDescending(o => o.DateCreated) 
      .ToList() 
      .Where(o => o.Paid == false); 

     return View(debts); 
    } 
+12

Respuesta simple: No se puede utilizar las propiedades que no se asignaron en consultas LINQ a las entidades! Solo las propiedades mapeadas se traducen a SQL. –

Respuesta

93

Entidad está tratando de convertir su propiedad pagados a SQL y no puede porque no es parte del esquema de la tabla.

Lo que puede hacer es dejar que la entidad consulte la tabla sin filtro Pagado y luego filtrar los que no son Pagos.

public ActionResult Index() 
{ 
    var debts = storeDB.Orders 
     //.Where(o => o.Paid == false) 
     .OrderByDescending(o => o.DateCreated); 

    debts = debts.Where(o => o.Paid == false); 

    return View(debts); 
} 

Eso, por supuesto, eso significaría que traer todos los datos de vuelta al servidor web y filtrado de los datos en él. Si desea filtrar en el servidor de bases de datos, puede crear una columna calculada en la tabla o usar un procedimiento almacenado.

16

Linq convierte las declaraciones en sentencias SQL y las ejecuta en la base de datos .

Ahora, esta conversión solo se produce para los miembros de las entidades, los inicializadores y las propiedades de navegación de entidades. Por lo tanto, para lograr una función u obtener una comparación de propiedades, primero debemos convertirlas en listas en memoria y luego aplicar funciones para recuperar datos.

tanto en su totalidad,

var debts = storeDB.Orders.toList() 
     .Where(o => o.Paid == false) 
     .OrderByDescending(o => o.DateCreated); 
+15

Sugeriría que pedirle a alguien que haga un toList() en los pedidos sea peligroso, ya que significaría recuperar toda la lista – elgrego

+0

Esto es bueno para mí porque mi propiedad problemática está en una función Sum Linq no en la cláusula Where. Así que no estoy obteniendo datos innecesarios y en los datos recibidos estoy haciendo la función Linq Sum que está trabajando en la Lista. ¡Gracias! ¡Lo que puede verse mal al principio puede ser muy útil en ciertas situaciones! –

21

sólo tenía que resolver un problema similar. Las soluciones anteriores requieren el procesamiento en memoria, lo cual es una mala práctica (carga diferida).

Mi solución fue escribir un ayudante que se volvió un predicado:

public static class Extensions 
{ 
    public static Expression<Func<Order, bool>> IsPaid() 
    { 
     return order => order.Payments.Sum(p => p.Amount) >= order.Total; 
    } 
} 

puede volver a escribir su declaración de LINQ como:

var debts = storeDB.Orders 
        .Where(Extensions.IsPaid()) 
        .OrderByDescending(o => o.DateCreated); 

Esto es útil cuando se desea volver a utilizar la lógica de cálculo (SECO). Lo malo es que la lógica no está en su modelo de dominio.

+1

Hay una serie de bibliotecas que intentan hacer este enfoque más "integrado", vea: http://stackoverflow.com/a/27383641/470183. Linq-to-entities se limita a las expresiones que utilizan las "Funciones canónicas", que se pueden convertir en SQL. C# 6 introdujo "Funciones de cuerpo de expresión" pero estas no son verdaderas lambdas (ver: http://stackoverflow.com/a/28411444/470183). Sin embargo, sería bueno tener esto en el marco, por lo tanto, el WIBNI https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/15087837-support-c-6-expression-bodied- function-members-in –

+1

Gracias por este ejemplo simple y conciso de 'Expression >'.Alguna vez lo entendí, pero parece obvio ahora. – AlexB

8

La otra razón es probablemente porque está utilizando IEnumerable de su propiedad, en lugar de ICollection

Así que en lugar de:

public class This 
{ 
    public long Id { get; set; } 
    //... 
    public virtual IEnumerable<That> Thats { get; set; } 
} 

Haga lo siguiente:

public class This 
{ 
    public long Id { get; set; } 
    //... 
    public virtual ICollection<That> Thats { get; set; } 
} 

Y vas hunky dory ... cosa estúpida para perder 2 horas más ...

11

T su problema también puede provenir de una propiedad [NotMapped] que tiene el mismo nombre en su modelo de DB y modelo de vista.

AutoMapper intenta seleccionarlo desde el DB durante una proyección; y la propiedad NotMapped obviamente no existe en el DB.

La solución es Ignore la propiedad en la configuración de AutoMapper al mapear desde el modelo de base de datos al modelo de vista.

  1. Busque un [NotMapped] propiedad con nombre Foo en su modelo DB.
  2. Busque una propiedad con el mismo nombre, Foo, en su Modelo de visualización.
  3. Si ese es el caso, cambie la configuración de AutoMapper. Añadir .ForMember(a => a.Foo, b => b.Ignore());
-1

me enfrentaba a este tema porque estaba teniendo una variable miembro, con sólo getwithout set propiedad

que es significa su auto calculated y not stored como una columna en the table

por lo tanto su not exist en el table schema

por lo make sure que cualquier variable miembro not auto calculated-have un getter y setter propiedades

Cuestiones relacionadas