Suppose, we have next 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 selector as Expression and store it in another place. In 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 to query syntax keeping Expression variable in-place?
UPD:
To clarify my question, I'm using DefaultIfEmpty for left join, it's 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 normally, because it compiles using inline Expression. It assigns null to Name field when there is no corresponding grunt. But if rewrite this query with call to external mapper method, it will be compiled to method call, which will get nullable grunt argument and will lead to 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);
}
Sure, I can add null-check into mapper method, but what I'm trying to achieve in my DAL is extract selectors into mapper classes and possibly omit null-checks there.
I'm not sure why you need the
Expression- just use theFunc. This should work: