我一直在使用模式从实体框架投影到业务域视图。我正在嵌套它,即从另一个投影中调用一个投影。它适用于集合,但我无法弄清楚如何使用相同的模式来投射单个实体。
对于集合,我的代码类似于:
public class PersonView
{
public int Id {get;private set;}
public string FullName { get; set; }
public static Expression<Func<Person, PersonView>> Projector = p => new PersonView {
Id = p.PersonId,
FullName = p.FirstName + " " + p.LastName
};
}
//...
context.People.Select(PersonView.Projector).ToList(); // returns a list of PersonViews
如果我创建一个包含1个元素的列表,或者使用LINQ获得创意,我可以让它工作,但如果可能的话,更喜欢更整洁的解决方案。
// convert single element to list, then project it. Works, but is messy
var orderDetails = context.Orders.Where(...)
.Select(o => new {
Id = o.Id,
Date = o.Date,
PersonView = new [] { o.Person }.AsQueryable().Select(PersonView.Projector).FirstOrDefault()
}).FirstOrDefault();
我想要类似的东西(下面不起作用,因为实体的linq不能调用Func&lt;&gt;):
public class PersonView
{
public int Id {get;private set;}
public string FullName { get; set; }
public static Func<Person, PersonView> ProjectorFn = p => new PersonView {
Id = p.PersonId,
FullName = p.FirstName + " " + p.LastName
};
public static Expression<Func<Person, PersonView>> ProjectorExpr = p => ProjectorFn(p);
}
var orderDetails = context.Orders.Where(...)
.Select(o => new {
Id = o.Id,
Date = o.Date,
PersonView = PersonView.ProjectorFn(o.Person)
}).FirstOrDefault();
//...
var peopleWithOrders = context.People.Where(p => p.Orders.Any())
.Select(PersonView.ProjectorExpr);
有什么建议吗?
答案 0 :(得分:1)
问题的实质是投影中的以下行
PersonView = PersonView.ProjectorFn(o.Person)
无法转换为商店查询,因为ProjectorFn
不再是Expression
,而是通用代理(Func<Person, PersonView>
)。
现在,您真正想要的是使用PersonView.Projector
字段中包含的原始表达式,但显然您无法调用它(不编译委托),因此无法返回您想要的{ {1}}输入。
LinqKit旨在使用自己的PersonView
扩展方法解决此问题,该方法在编译代码时会确保将表达式替换回原始格式。
要启用拦截,您必须使用扩展实体集的Invoke()
方法:
AsExpandable()
答案 1 :(得分:0)
您需要继续使用直接表达式树,但也要将其编译为普通委托:
public static readonly Func<Person, PersonView> ProjectorFunc = Projector.Compile();