如何重构EF选择的部分

时间:2012-11-14 21:48:46

标签: entity-framework

假设我有以下EF代码:

context.Employees.Select(e => e
{
    FullName = e.FirstName + " " + e.LastName,
    StartDate = e.StartDate,
    ... // Grab other data
};

现在也许我注意到我在多个地方构建了全名,但是想要集中管理。有可能重构这个吗?

如果我将它设为方法或Func,我会收到EF错误,因为它无法将其转换为SQL。

注意:这是一个简单的例子,假设它可以通过“选择”,“在哪里”,任何在赋值中变得更加复杂,因此添加ToList然后运行其他代码将是次优的并且不适合重构的定义,因为我必须改变功能,而不仅仅是让它更易于维护。

2 个答案:

答案 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;}}
}