假设我有以下EF代码:
context.Employees.Select(e => e
{
FullName = e.FirstName + " " + e.LastName,
StartDate = e.StartDate,
... // Grab other data
};
现在也许我注意到我在多个地方构建了全名,但是想要集中管理。有可能重构这个吗?
如果我将它设为方法或Func,我会收到EF错误,因为它无法将其转换为SQL。
注意:这是一个简单的例子,假设它可以通过“选择”,“在哪里”,任何在赋值中变得更加复杂,因此添加ToList然后运行其他代码将是次优的并且不适合重构的定义,因为我必须改变功能,而不仅仅是让它更易于维护。
答案 0 :(得分:0)
一种解决方案是使用LinqKit中的AsExpandable
方法:
Expression<Func<Employee,string>> fullName = e => e.FirstName + " " + e.LastName;
context.Employees.AsExpandable().Select(e => e
{
FullName = fullName.Compile().Invoke(e),
StartDate = e.StartDate,
... // Grab other data
};
来自链接文章:
Compile是Expression类中的内置方法。它转换了 表达成一个普通的Func 满足编译器。当然,如果这种方法真的运行了,我们就会 最终得到编译的IL代码而不是表达式树和LINQ SQL或Entity Framework会抛出异常。但是这是 聪明的部分:编译从未实际运行; LINQ to SQL或 实体框架永远都能看到它。对Compile的调用被剥离 完全由一个通过调用创建的特殊包装器完成 AsExpandable,并替换正确的表达式树。
或者,您可以考虑使用Entity Framework创建Model Defined Function。如果要在Employee类本身上定义FullName属性,还有Microsoft.Linq.Translations库。
答案 1 :(得分:0)
我认为在实体类本身中更好的集中方式。您可以将ReadOnly属性添加到您应该为NotMapped
的实体类,以返回所需的格式化数据。
Public class Employee
{
//...
public string fullName{get { return FirstName + " " + LastName;}}
}