如何在LINQ-to-Entities查询中使用自定义属性?

我有一个类Post ,它是一个Entity Framework模型。 它包含这样的属性:

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

我可以在这样的查询中使用它:

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

但是当我有一个使用它的属性时,就像这样

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

然后我做不到:

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

它说:

LINQ to Entities不支持指定的类型成员“Showable”。 仅支持初始化程序,实体成员和实体导航属性。

如果将属性编写为可翻译为SQL的Expression ,则可以执行此操作。

这是怎么做的。

这有点复杂,因为它是复杂问题的一般解决方案。

一般的想法是这样的:LINQ to Entities(像所有 LINQ提供者一样)无法在运行时将编译后的代码(如属性)转换为SQL。 LINQ to Objects可以执行已编译的代码,但无法对其进行转换 。 但他们可以翻译Expression 。 所以你可以写:

 public static Expression> WhereActive { get { return p => p.Public && p.PublishedDate > DateTime.Now; } } 

然后你可以写:

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

……和LINQ to Entities可以翻译它。 postI链接中的代码概括了这个想法。

遗憾的是,entity framework根本不支持计算属性(也就是说,返回计算值而不是对支持字段的引用的属性),但可能在将来的日期支持它。

我认为最简单的方法是使用本答案中提到的DelegateDecompiler.EntityFramework包的Computed属性。