So I'm trying out Azure's new DocumentDB. Unfortunately it doesn't allow selectors to a type. It won't let me do:
public IEnumerable<U> GetAll<U>(Expression<Func<T, U>> selector)
{
return Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
.Select(selector)
.AsEnumerable();
}
and use it as:
// Doesn't work
return GetAll(t => new MyViewModel {
Id = t.Id,
Name = t.Name,
Email = t.Email,
Url = t.Url
});
It says it only supports anonymous types. (I imagine since it's fairly new that will change at some point).
I can solve the problem using a second select:
return GetAll(t => new {
Id = t.Id,
Name = t.Name,
Email = t.Email,
Url = t.Url
}).Select(t => new MyViewModel() {
Id = t.Id,
Name = t.Name,
Email = t.Email,
Url = t.Url
}).AsEnumerable();
However that is a pain.
Is there a way to use the same selector twice and just make it anonymous the first time?
You'll notice the signature for
GetAll
containsExpression<Func<T, U>> selector
. TheExpression
part says that this argument is being passed as an expression tree and not as aFunc
delegate. It's done this way so that the provider can parse the selector and generate the appropriate database calls (often SQL) to fetch your data.Now, when you use a specific custom type - in your case
MyViewModel
- the provider hits a problem - it just doesn't know how to convert that type into the database calls. It does know how to translate an anonymous type though.In then returns an
IEnumerable<U>
so data returned byGetAll
is now in memory so you can then perform the subsequent creation of theMyViewModel
type. There's no need to translate to database calls any more.So the answer is that this is by design. It is very unlikely that this will be a new feature in the future.