I have been using a pattern for projecting from Entity Framework to business domain views. I am nesting it, i.e. calling one projection from within another projection. It works well for collections, but I can't work out how to use the same pattern for projecting a single entity.
For collections, my code looks something like:
public class PersonView
{
public int Id {get;private set;}
public string FullName { get; set; }
public static Expression<Func<Person, PersonView>> Projector = p => new PersonView {
Id = p.PersonId,
FullName = p.FirstName + " " + p.LastName
};
}
//...
context.People.Select(PersonView.Projector).ToList(); // returns a list of PersonViews
If I create a list containing the 1 element, or otherwise get creative with the LINQ, I can get it to work, but would prefer a neater solution if possible.
// convert single element to list, then project it. Works, but is messy
var orderDetails = context.Orders.Where(...)
.Select(o => new {
Id = o.Id,
Date = o.Date,
PersonView = new [] { o.Person }.AsQueryable().Select(PersonView.Projector).FirstOrDefault()
}).FirstOrDefault();
I would like something like (the below does not work, because linq to entities cannot invoke the Func<>):
public class PersonView
{
public int Id {get;private set;}
public string FullName { get; set; }
public static Func<Person, PersonView> ProjectorFn = p => new PersonView {
Id = p.PersonId,
FullName = p.FirstName + " " + p.LastName
};
public static Expression<Func<Person, PersonView>> ProjectorExpr = p => ProjectorFn(p);
}
var orderDetails = context.Orders.Where(...)
.Select(o => new {
Id = o.Id,
Date = o.Date,
PersonView = PersonView.ProjectorFn(o.Person)
}).FirstOrDefault();
//...
var peopleWithOrders = context.People.Where(p => p.Orders.Any())
.Select(PersonView.ProjectorExpr);
Any suggestions?