【发布时间】:2015-10-22 01:53:19
【问题描述】:
我有一个项目,它允许通过装饰器和接口实现一些计算属性和业务逻辑,这些接口控制对 EF 代码第一层的所有访问。我想通过 oData 公开这个业务逻辑层,并允许标准的 IQueryable 功能来过滤、排序和分页。由于各种原因,我需要将查询应用于数据库级别,而不仅仅是通过 Linq 生成 IEnumerable to Objects 查询。
我的类结构类似于 LogicClass(Repository) > Interface > Decorator > Poco。这些类看起来像:
public class PeopleLogicLayer
{
// ... business and query logic ...
// basic query used internally
private System.Linq.IQueryable<PersonEfPoco> GetQuery()
{
if (this.CurrentQuery == null) this.ResetQuery();
var skipQuantity = (this.Page <= 1) ? 0 : (this.Page - 1) * this.PageSize;
return this.CurrentQuery.Skip(skipQuantity)
.Take(this.PageSize)
.AsQueryable();
}
}
public interface IPerson
{
int Id { get; set; }
String FirstName { get; set; }
String LastName { get; set; }
String FullName { get; }
}
public class PersonEfPoco
{
public int Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
}
public class PersonDecorator : IPerson
{
private PersonEfPoco _person;
public PersonDecorator(PersonEfPoco person)
{
this._person = person;
}
public int Id
{
get { return this._person.Id; }
set { this._person.Id = value; }
}
public String FirstName
{
get { return this._person.FirstName; }
set { this._person.FirstName = value; }
}
public String LastName
{
get { return this._person.LastName }
set { this._person.LastName = value }
}
public String FullName
{
get { return $"{this._person.FirstName} {this._person.LastName}"; }
}
}
我想要做的是:
List<IPerson> peopleNamedBob =
from o in (new PeopleHiddenBehindBusinessLogic()) where o.FirstName == "Bob" select o;
或
List<IPerson> peopleNamedBob =
(new PeopleHiddenBehindBusinessLogic()).Where(o => o.FirstName == "Bob").ToList();
这是一个过度简化。实际上不可能通过“select new PersonDecorator(o)”进行查询内转换,因为装饰层中有复杂的逻辑,并且在其中处理,我们不想允许直接访问 EF层,而不是更喜欢将查询保留在装饰器的更抽象层上。
我考虑过像here 提到的那样从头开始实现自定义 Linq 提供程序。但是那篇文章已经过时了,我认为在过去的 5 年里有更好的方法。我发现re-linq 听起来很有潜力。但是,当我搜索 re-linq 的教程时,没有太多内容可供选择。
据我所知,高级步骤是创建访问者以替换查询的主题并转换过滤器表达式以匹配 poco(如果它可以,大多数属性名称都会匹配)并将其传递给 EF。然后保存与 EF Poco 不兼容的表达式,以便稍后过滤最终的装饰集合。 (暂时不考虑分页的复杂性)
更新
我最近发现了支持 Linq 的流畅方法,但我仍然缺乏关于如何分解“Where”表达式的信息,目的是在 PersonEfPoco 上使用 IPerson 的过滤器。
这让我做出了选择。
那么最新的方法是什么?
【问题讨论】:
标签: c# entity-framework linq linq-to-sql