Linq-to-SQL, pass Expression <Func <T, T >> to select a method in the query syntax
Suppose we have the following code:
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 }; } I want to extract the selector as an expression and save it elsewhere. In the method syntax, it will look like this:
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); } Is it possible to convert this LinqToSql method chain into query syntax while keeping the Expression variable in place?
UPD:
To clarify my question, I am using DefaultIfEmpty for the left join, this is a short form of equal query:
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 }; } which works fine because it compiles using the inline expression. It assigns null to the Name field if there is no corresponding grunt . But if you rewrite this request with a call to the mapper external method, it will be compiled by a method call that will receive a nullable grunt argument and will throw a 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); } Of course, I can add null-check to the mapper method, but what I am trying to achieve in my DAL are selectors of selectors in the mapping classes and possibly omit null checks.
I'm not sure why you need Expression - just use Func . This should work:
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) } You cannot always use query syntax; there are times when you can express calculations only using chains of methods. In this particular case, the query syntax introduces a lambda behind the scenes if the predicate was inline, but you put it in a variable, so you have no way to specify how to use this variable, like with a lambda supported by the query syntax.