假设我有一个看起来像这样的OData查询(我的实际查询要复杂得多):
Orders.Select(z => new { z.SubOrder.Addresses,
z.SubOrder.Cost,
z.SubOrder.SubOrderId,
z.Sequence});
这很好用。除了Address对象上有一个子对象(StateRef)。由于StateRef在State表上进行查找,因此返回为null。
为了说明,下面是地址对象Address的外观示例:
Address:
string Street 1
string Street 2
StateRef PrimaryState
string City
// ... 42 other string attributes not shown ...
StateRef
对象上有州名,但也有一些其他重要的州属性(也许是州鸟?)
所以,我想知道的是,我现在必须为z.SubOrder.Addresses创建一个“子投影”,其中包含所有46个属性,以便我可以访问PrimaryState
项目吗? (我希望不)
除了更多编码之外,它还意味着我必须使用匿名类型。这使我的映射必须是手动(而不是使用AutoMapper)。
那么我想要的是一种在投影中“扩展”StateRef的方法吗?
这样的事情:
Orders.Select(z => new { z.SubOrder.Addresses.Expand("PrimaryState"),
z.SubOrder.Cost, ^
z.SubOrder.SubOrderId, |
z.Sequence}); |
|
// This is not allowed by the compiler ----------+
尝试此操作会出现此错误:
无效的匿名类型成员声明符。必须使用成员分配,简单名称或成员访问声明匿名类型成员。
更新 这是一个示例查询来说明我的问题:
Users.Take(10).Select(x=>new { x.Id, x.Reputation, x.Comments})
针对“data.stackexchange.com/stackoverflow/atom”运行该操作。您将看到Comments有一个返回null的Post对象。
我需要它来返回它内部的值。
注意:我知道我可以手动将所有这些输入到“子”投影中。请阅读上面我不想要的原因。
答案 0 :(得分:7)
当然可以这样做。要获得概念验证,请尝试执行此操作:
var uri = new Uri( "http://data.stackexchange.com/stackoverflow/atom/Users()?$top=10&$expand=Comments/Post&$select=Id,Reputation,Comments/" );
entities.Execute<User>( uri, "GET", false ).Select( x => new { x.Id, x.Reputation, x.Comments } );
expand的正确用法是这样的:
entities.Users.Expand( "Comments/Post" ).Take( 10 ).ToArray();
我不知道为什么图书馆的作者决定不允许使用扩展和投影,但正如上面的概念证明所示,当然可以这样做。
如果您不介意接收整个用户并在此之后进行投影,则可以使用第二个示例。否则,您可以编写自己的助手,从第一个示例中生成URI,执行它们,然后添加投影。
答案 1 :(得分:2)
您不必创建列出所有46个属性的子投影,例如
(from u in Users
select new
{
u.Id, u.Reputation,Comments = ( from c in u.Comments
select new YourClass {comment = c,
post= c.Post})
}
)
.Take(10)
.....
public Class YourClass
{
public Comment comment {get; set;}
public Post post {get;set;}
}
不完全是我想象你想要的对象图。
除此之外,人们可以花大量时间尝试编写一个能够生成正确OData查询的LinQ表达式,我们发现使用Expand,Filter创建自己的OData查询类是更加有效的时间。选择属性等即直接编写OData查询而不是尝试编写LinQ查询。
答案 2 :(得分:1)
你可以,
Users.Take(10).Select(x=>new { Id = x.Id, Reputation = x.Reputation, Comments = x.Comments.Select(c =>c.Id) })
这会产生请求,
答案 3 :(得分:0)
Expand
已在查询中完成。见How to: Load Related Entities (WCF Data Services)
你想要这样的东西:
Orders
.Expand("StateRef")
.Select(z => new { ... } );
答案 4 :(得分:0)
您可以从子对象中选择特定属性。
e.g。在StackOverflow的示例中,我可以在LINQPad中成功执行以下查询。
Users
.Take (10)
.Select(x => new {x.Id, x.Reputation, CommentsText = x.Comments.Select(c => c.Text)})
在您的情况下,您可以编写如下查询:
Orders.Select(z => new { StateName = z.SubOrder.Addresses.Select(a => a.PrimaryState),
z.SubOrder.Cost,
z.SubOrder.SubOrderId,
z.Sequence});