假设我们有以下代码:
当然,我可以在映射器方法中添加空值检查,但我在DAL中试图实现的是将选择器提取到映射器类中,并可能在那里省略空值检查。
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 };
}
这段代码在使用内联表达式编译时可以正常工作。当没有对应的grunt
时,它会将null
赋值给Name字段。但是,如果将此查询重写为调用外部映射器方法,则会编译为方法调用,该方法将获取可为空的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中试图实现的是将选择器提取到映射器类中,并可能在那里省略空值检查。
Func
,由于grunt
可能等于 null,它将抛出 TargetInvocationException 和内部 NullReferenceException。但是,如果以方法链格式传递表达式给 Select 方法,则可以正常工作。 - dmitry.sDefaultIfEmpty
能够返回一个非空对象吗?即使对象的属性为空?这好奇怪啊。 - Rawling