2011-03-22 213 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的外键。如果情况并非如此,则需要相应修改。

希望有所帮助。