Reputation: 73
So, I have been using AutoMapper with the IQueryable extensions to select some really simple viewmodels for list views. This allows me to not load up an entire entity framework object, but I have ran into a little bit of a less than ideal situation where I need to pull a simple viewmodel for a single complex object.
userQuery.Where(u => u.Id == id).ProjectTo<SimpleUserViewModel>().FirstOrDefault();
I could do a normal AutoMapper.Map, but this pulls in the whole object and child objects, when I may only need a single property off of the child and I don't want to eat the database retrieval cost.
Is there a better way of approaching this for getting a single entity and emitting a select through entity framework for only grabbing the necessary objects?
Upvotes: 7
Views: 3845
Reputation: 13773
It does look inefficient, but it isn't.
Just like many other LINQ methods, most notably the Select
which it replaces, ProjectTo<>
relies on deferred execution. It won't pull the data until it reaches the point of having to present (or act on) the data.
Common ways to trigger this execution are ToList
, First
, Single
(including the OrDefault
and Async
variants for all of them). Essentially, any action that requires actual knowledge of the data set itself.
I know the feeling, it feels less elegant to not be able to do something like ProjectToSingle<SimpleUserViewModel>(x => x.Id == id)
. If it really bothers you, you can write this wrapper method yourself, essentially translating it to a Where
/ProjectTo
/Single
chain.
I feel the same way, but I've gotten used to writing Where
/ProjectTo
/Single
and it doesn't feel wrong anymore. It's still a lot better than having to write the include statements.
Also, as an aside, even if you weren't using Automapper, but you'd still want to cut down on the columns that you fetch (because you know you won't need all of them) instead of loading the whole entity, you'd still be required to use a Where
/Select
/Single
method chain.
So Automapper didn't make the syntax any less elegant than it already was with regular LINQ/EF.
Upvotes: 7