2013-02-08 80 views
10

说我有一个OData的查询,看起来像这样的投影(选择)(我的实际查询要复杂得多):展开了WCF数据服务(OData的)

Orders.Select(z => new { z.SubOrder.Addresses, 
         z.SubOrder.Cost, 
         z.SubOrder.SubOrderId, 
         z.Sequence}); 

这工作得很好。除Address对象上有一个子对象(StateRef)。由于StateRef在状态表上进行查找,它将返回为空值。

为了说明,这里的地址对象地址可能外观的示例:

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 ----------+ 

尝试这给这个错误:

Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.

更新: 下面是一个例子查询来说明什么,我问:

Users.Take(10).Select(x=>new { x.Id, x.Reputation, x.Comments}) 

针对“data.stackexchange.com/stackoverflow/atom”运行。你会看到Comments有一个返回null的Post对象。

我需要那个返回里面的值。

注意:我知道我可以手动输入到“子”投影中。阅读上面为什么我不想要那样。

+0

因为只有展开,似乎在第一个孩子的工作就可以反转查询?因此,对于您的SO示例,请从评论开始,例如(c => c.User).Expand(c => c.Post).Take(10) – Phil 2013-02-11 17:53:39

+0

@Phil,Alas,no。这个例子很简单,但我的实际查询非常复杂,有几个“子部分”。 – Vaccano 2013-02-11 19:16:00

+0

链接已死。 – 2017-08-29 15:28:52

回答

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 }); 

扩大的正确用法是这样的:

entities.Users.Expand("Comments/Post").Take(10).ToArray(); 

我不知道为什么图书馆的作家们决定用与扩大到禁止预测,但正如上述概念证明所示,这样做肯定是可行的。

如果您不介意接收整个用户并在此之后进行投影,则可以使用第二个示例。否则,您可以编写自己的帮助程序,它将从第一个示例中生成URI,然后执行它们,然后添加投影。

+0

非常非常有趣......所以服务器允许它,而不是客户端库。我认为这回答我的问题。 – Vaccano 2013-02-15 22:37:47

0

Expand在查询上完成。见How to: Load Related Entities (WCF Data Services)

你想要的东西,如:

Orders 
    .Expand("StateRef") 
    .Select(z => new { ... }); 
+0

这会导致以下异常:* NotSupportedException:无法在同一查询中指定明确展开的情况下创建投影。* – Vaccano 2013-02-08 22:41:03

+0

请显示订单查询的完整代码。您可以在.Expand参数中使用逗号进行多次展开。 – 2013-02-08 22:43:43

+0

但是你不能有一个扩展子句和一个select子句。在任何查询和任何端点上。我使用了Expand,因为这是我正在寻找的功能。但是我从来没有能够将Expand和Select结合起来。如果您可以请发表示例(针对Netflix或StackOverFlows提要)。 – Vaccano 2013-02-08 22:47:43

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查询。

+0

我不知道你能做到这一点。这解决了我的一半问题。(我仍然有一个匿名类型,我不能使用AutoMapper)。如果没有人回答完整的答案,那么我会选择你的答案。 – Vaccano 2013-02-11 19:18:47

+0

您可以创建一个具体类型来代替匿名类型。例如class MyProjection {int Id {...},...};选择新的MyProjection {Id = u.Id ...} – Phil 2013-02-11 19:21:46

+0

正如菲尔所说,匿名类型可以被替换。我已经扩展了上面的代码片段,以显示如何替换嵌套的匿名类型。 – 2013-02-12 10:08:23

0

您可以从子对象中选择特定的属性。

例如在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}); 
+0

这基本上是在做另一个投影,我最终得到了匿名类型。 – Vaccano 2013-02-11 20:47:05