2013-02-08 93 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

相關問題