次のコードがあるとします。
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を使用しています。これは、等しいクエリの短い形式です。
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
対応するがない場合は、[名前]フィールドに割り当て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で達成しようとしているのは、セレクターをマッパークラスに抽出し、そこでヌルチェックを省略することです。