假设,我们有下一个代码:
public class Dto
{
public int Id;
public string Name;
}
...
using (var db = new NorthwindDataContext())
{
var q = from boss in db.Employees
from grunt in db.Employees.Where(p => p.ReportsTo == boss.EmployeeID).DefaultIfEmpty()
select new Dto { Id = boss.EmployeeID, Name = grunt.FirstName };
}
我想将选择器提取为表达式并将其存储在另一个地方。在方法语法中,它将如下所示:
Expression<Func<Employee, Employee, Dto>> selector = (boss, grunt) => new Dto
{
Id = boss.EmployeeID, Name = grunt.FirstName
};
using (var db = new NorthwindDataContext())
{
var q = db.Employees.SelectMany(boss => db.Employees.Where(p => p.ReportsTo == boss.EmployeeID).DefaultIfEmpty(), selector);
}
是否可以将此 LinqToSql 方法链转换为保持 Expression 变量就地的查询语法?
升级版:
为了澄清我的问题,我使用 DefaultIfEmpty 进行左连接,它是相等查询的一种简短形式:
using (var db = new NorthwindDataContext())
{
var q = from boss in db.Employees
join stub in db.Employees on boss.EmployeeID equals stub.ReportsTo into stubi
from grunt in stubi.DefaultIfEmpty()
select new Dto { Id = boss.EmployeeID, Name = grunt.FirstName };
}
它可以正常工作,因为它使用内联表达式进行编译。null
当没有对应的 时,它分配给 Name 字段grunt
。但是如果用调用外部映射器方法重写这个查询,它将被编译为方法调用,这将得到可为空grunt
的参数,并会导致 NullReferenceException:
public static Dto GetDto(Employee boss, Employee grunt)
{
return new Dto
{
Id = boss.EmployeeID,
Name = grunt.FirstName
};
}
using (var db = new NorthwindDataContext())
{
var q = from boss in db.Employees
join stub in db.Employees on boss.EmployeeID equals stub.ReportsTo into stubi
from grunt in stubi.DefaultIfEmpty()
select GetDto(boss, grunt);
}
当然,我可以在映射器方法中添加空检查,但我在 DAL 中试图实现的是将选择器提取到映射器类中,并可能在那里省略空检查。