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: