2010-02-11 9 views
16

Tengo una clase Post que es un modelo Entity Framework. Contiene una propiedad como esta:¿Cómo se usa una propiedad personalizada en una consulta LINQ-to-Entities?

public bool Showable { 
    get { 
    return this.Public && this.PublishedDate > DateTime.now 
    } 
} 

que se puede utilizar en una consulta como esta:

from p in db.Posts where p.Showable select p; 

pero cuando tengo una propiedad que lo utiliza, como este

public IEnumerable<Post> ShowablePosts { 
    get { 
    return from p in db.Posts where p.Showable select p; 
    } 
} 

entonces no puedo hacer:

from p in ShowablePosts where p.Id > 42 select p; 

Es s ays:

El miembro de tipo especificado 'Showable' no es compatible con LINQ to Entities. Solo se admiten inicializadores, miembros de entidades y propiedades de navegación de entidades.

Respuesta

1

Desafortunadamente, el marco de la entidad simplemente no soporta propiedades calculadas (es decir, una propiedad que devuelve un valor calculado en lugar de una referencia a un campo de respaldo), pero it may be supported at a future date.

+0

Puedo llamar propiedades bien calculadas en una consulta, pero no en un método que ejecuta una consulta. Es raro. – Pablo

+0

Vivo en el mundo de Linq a SQL en este momento, es 'return from p en db.Posts donde p.Showable select p;' nativa y 'IQueryable ' o 'IEnuemerable ' en EF? ¿Y eso importaría en su pregunta? –

+0

@J. Pablo Fernández: la consulta de Linq no se ejecuta cuando los defines, solo cuando haces algo que requiere los resultados reales. Hay muchas cosas que Linq soporta, pero que Entity Framework no hace, y estas cosas solo se vuelven obvias al ejecutar la consulta. –

19

Puede hacer esto si escribe la propiedad como Expression que se puede traducir a SQL.

Here's how to do it.

que es un poco complicado, porque es una solución general a un problema complicado.

La idea general es esta: LINQ to Entities (como todos proveedores LINQ) no puede traducir el código compilado como su propiedad a SQL en tiempo de ejecución. LINQ to Objects puede ejecutar código compilado, pero no puede traducir it. Pero ellos pueden traducen Expression<T>. Así se podría escribir:

public static Expression<Func<Post, bool>> WhereActive 
{ 
    get 
    { 
     return p => p.Public && p.PublishedDate > DateTime.Now; 
    } 
} 

entonces se podría escribir:

public IEnumerable<Post> ShowablePosts 
{ 
    get 
    { 
     return db.Posts.Where(WhereActive); 
    } 
} 

... y LINQ a Entidades que podrían traducirse. El código en el enlace post I generaliza esta idea.

+0

¿Hay alguna manera de pasar un parámetro a Where Active? Por ejemplo, el DateTime. Si es así, es posible que pueda responder https: // stackoverflow.con/q/48497487/2968001 –

0

Creo que la manera más fácil de hacerlo es usando el atributo Computed del paquete DelegateDecompiler.EntityFramework que se menciona en this answer.

Cuestiones relacionadas