I like to do projection from my entity models into my view models using extension methods. This means I dont over/under fetch for my models and it makes the code nice and readable. It makes sense that sometimes the projections may include nested models, and I want to get reuse on those sub-projections.
I want to be able to do something like the following:
ctx.People.FiltersAndThings().ToViewModels();//the project my DB Models into view models
Extension methods for actual projection
public static IQueryable<PersonModel> ToViewModels(this IQueryable<Person> entities)
{
return entities.Select(x => new PersonModel {
Me = x.Me.ToViewModel(), //this method cannot be translated into a store expression
Friends = x.Friends.AsQueryable().ToViewModels() //works fine with some magic (tm)
});
}
public static IQueryable<ProfileModel> ToViewModels(this IQueryable<Profile> entities)
{
return entities.Select(x => new ProfileModel { Name = x.Name });
}
public static ProfileModel ToViewModel(this Profile entity)
{
return new ProfileModel { Name = entity.Name };
}
When using a Queryable (eg Friends = x.Friends.AsQueryable().ToViewModels()
) we can use some magic to flatten this to an expression (see https://stackoverflow.com/a/10726256/1070291, answer by @LordTerabyte) But when we are doing an assignment with a new clause (eg Me = new ProfileModel { Name = x.Me.Name }
) its not an expression so if we bundle this under an extension method (eg Me = x.Me.ToViewModel()
) we can't flatten this to an expression.
How does an assignment to a new object work under the scenes in EF?
Is there a way to do convertion to a new object via an extension method?
Full demo code here: https://github.com/lukemcgregor/ExtensionMethodProjection
Edit:
I now have a blog post (Composable Repositories - Nesting Extensions) and nuget package to help with nesting extension methods in linq