Linq-to-SQL,传递表达式<Func<T,T>>以选择查询语法中的方法



假设,我们有下一个代码:

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方法链转换为查询语法,将表达式变量定为就地?

upd:

为了澄清我的问题,我正在使用Defaultifempty进行左JOIN,这是一种相等查询的简短形式:

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

正常工作的

,因为它使用内联表达式编译。当没有相应的grunt时,它将null分配给字段。但是,如果通过呼叫对外部映射器方法进行调查,将其编译为方法调用,该方法将获得可确定的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);
}

当然,我可以将null-Check添加到mapper方法中,但是我在DAL中要实现的目标是将选择器提取到映射器类中,并可能省略那里的null-checks。

我不确定为什么需要Expression-只需使用Func即可。这应该有效:

Func<Employee, Employee, Dto> selector = (boss, grunt) => new Dto 
{ 
Id = boss.EmployeeID, Name = grunt.FirstName 
}; 
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 selector(boss, grunt)
} 

您不能始终使用查询语法,在某些情况下,您只能使用方法链表示计算。在这种特定情况下,查询语法如果谓词是内联的,则将在幕后引入lambda,但是您将其放入变量中,因此您无法指定应该如何使用该变量,就像使用lambda一样,通过查询语法。

相关内容

  • 没有找到相关文章

最新更新