所以我正在尝试Azure的新DocumentDB。不幸的是,它不允许选择器类型。它不会让我做:
public IEnumerable<U> GetAll<U>(Expression<Func<T, U>> selector)
{
return Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
.Select(selector)
.AsEnumerable();
}
并将其用作:
// Doesn't work
return GetAll(t => new MyViewModel {
Id = t.Id,
Name = t.Name,
Email = t.Email,
Url = t.Url
});
它说它只支持匿名类型。(我想因为它是相当新的,会在某个时候发生变化)。
我可以使用第二个选择来解决问题:
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();
然而,这是一种痛苦。
有没有办法两次使用相同的选择器并在第一次使其匿名?
注意到GetAll
的签名包含Expression<Func<T, U>> selector
。Expression
部分表示此参数作为表达式树传递,而不是作为Func
委托传递。这样做是为了让提供程序可以解析选择器并生成适当的数据库调用(通常是 SQL)来获取数据。
现在,当您使用特定的自定义类型时(在您的情况下MyViewModel
- 提供程序遇到问题 - 它只是不知道如何将该类型转换为数据库调用。不过,它确实知道如何翻译匿名类型。
In then 返回一个IEnumerable<U>
,因此 GetAll
返回的数据现在位于内存中,以便您可以执行 MyViewModel
类型的后续创建。无需再转换为数据库调用。
所以答案是这是设计使然。这不太可能成为未来的新功能。