假設,我們有下面的代碼:LINQ到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方法鏈查詢語法保持Expression變量就地轉化?
UPD:
爲了澄清我的問題,我使用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
分配給名稱字段。但是,如果重寫此查詢與調用外部映射器的方法,它會被編譯到方法調用,這將讓可空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,它將拋出帶有內部NullReferenceException的TargetInvocationException。但它通常以傳遞給方法鏈格式中的Select方法的表達式工作。 – Harm
@Harm你是否確信?雙精度型的'select'只是被編譯器翻譯成了對'SelectMany'的調用。無論如何,如果你擔心空咕嚕聲,爲什麼你打電話給DefaultIfEmpty_? – Rawling
@Rawling,是的,我確定。我爲左連接調用DefaultIfEmpty。我更新了該問題以進行澄清。 – Harm