2011-03-22 210 views
1

我目前一類供應商的名單,這家供應商類中的訂單列表。幫助LINQ查詢

每個訂單具有用戶ID和用戶名空字符串變量。

我再有一個用戶列表包含用戶ID和用戶名。

我現在這樣做的方法是:

foreach(supplier s in SupplierList) 
{ 
    foreach (order o in s.childorders) 
    { 
     user u = _users.First(p => p.userid == o.userid); 
     o.username = u.username; 
    } 
} 

我覺得這可能是有點低效,我不知道是否有可能壓縮它分解成一個LINQ查詢?

邏輯應

組supplierslist.childorders.username到其中_users值supplierslist.childorders.userid == _users.userid

林相當新的LINQ所以這方面的任何建議,將apreciated,或者也可以如果它是一個糟糕的主意,並離開它,因爲它是/原因將是一件好事。

感謝

回答

1
var orderUserPairs = SupplierList 
    .SelectMany(s => s.ChildOrders) 
    .Join(_users, o => o.UserId, u => u.userId, (Order, User) => new {Order, User}); 

foreach (var orderUserPair in orderUserPairs) 
    orderUserPair.Order.username = orderUserPair.User.username; 

雖然兼具usernameuserId出定單的一部分看起來可疑。

+0

訂單實際上不包含用戶名,在這種情況下,'真正的'訂單類只包含userID,我使用MVVM並且在Order和我的UI之間有一個類,它支持propertychanged,並且包含UserName,因爲用戶名只顯示在UI 。 – Purplegoldfish 2011-03-22 17:19:55

2

你想在這裏做的是遍歷集合(衆多的收藏品,真的,但它不會有所作爲)和發生變異其成員。 LINQ並不是真正針對執行變異操作,而是在查詢。你可以用LINQ來完成,但它是against the spirit of the tool

如果您自己構建SupplierList,則可能可以使用LINQ適當地獲取數據,以便它按照您的需要進行預填充。

否則,我會離開foreach,因爲它是。您可以創建一個字典,將用戶ID映射到內部循環,但這是您的調用,取決於您的數據大小。

+0

+1這幾乎是我會說的。 – Tejs 2011-03-22 17:06:03

1

如果用戶列表包含很多元素,它可以是很慢,所以我會使用一個臨時詞典:

var userById = users.GroupBy(x => x.userid) 
        .ToDictionary(x => x.Key, x => x.First()); 

foreach(var order in supplier.SelectMany(x => x.childorders)) 
{ 
    order.username = userById[order.userid].username; 
} 
+0

這是填寫錯誤,固定(我希望):S – digEmAll 2011-03-22 17:16:13

+0

我認爲'加入'它比'詞典'更好的分組,因爲'加入'有更多的信息關於哪些項目將被加入。 – Snowbear 2011-03-22 17:17:55

+0

@SnowBear:我剛剛翻譯了他發佈的代碼,通過字典查找改進了用戶名稱檢索。在這裏使用加入我沒有看到任何明顯的優勢... – digEmAll 2011-03-22 17:23:39

1

您需要使用或的SelectMany取決於天氣您使用LINQ到SQL或LINQ與當地收藏加入。如果您使用本地集合,更好的方法是使用連接,否則使用SelectMany。

就像這個...加入:

var selection = (from s in SupplierList 
       join o in s.childholders on s.userid equals o.userid 
       select new { username = o.username); 

,或者在LINQ到SQL的情況:

var selection = (from s in SupplierList 
       from o in s.childholders 
       select { username = o.username); 

然後,您可以使用您投射您想要的方式匿名類型。

+0

小點...我想你需要在你的連接中說'等於',而不是'=='。 – nycdan 2011-03-22 17:16:28

+0

@nycdan:correct :) – TheBoyan 2011-03-22 17:19:13

1

我同意喬恩,但你可以

var orders = (from s in supplier 
       from o in s.childorders 
       select new 
       { 
        Order = o, 
        User = _users.First(p => p.userid == o.userid) 
       }).ToList(); 

foreach(var order in orders) { 
    order.Order.username = order.User.username; 
} 

未經測試的過程:)

+0

你在最後一行設置匿名類型的'用戶名'。你還沒有測試過,但我們的思維彙編技巧很強大! – Snowbear 2011-03-22 17:16:26

+1

噢,呃,我剛剛意識到我做了什麼。無論如何,其他答案都比我好。更新:固定? – Tom 2011-03-22 17:19:31

1

首先一個問題...

它看起來就像你在每個操作訂購。爲什麼您需要先循環瀏覽供應商列表,因爲您似乎沒有在循環中使用它?除非有訂單不屬於任何供應商列表,否則您可能會跳過該步驟。

如果情況並非如此,那麼我認爲你可以使用連接。如果你不熟悉的加入在LINQ的語法,這是一個(簡單)的方式來解決:

var x = from S in SupplierList 
     join C in childorders on C.supplierlistID equals S.ID 
     where [whatever you need here if anything] 
     select new { field1, field2}; 
foreach var y in x 
{ 

} 

注意我假定childorders到supplierlist的外鍵。如果情況並非如此,則需要相應修改。

希望有所幫助。