如何提高我的LINQ

时间:2014-03-07 10:59:44

标签: c# linq

以下查询确实解决了我的问题,但它似乎过于复杂。

问题是我有一个存储菜单选项(id,名称,描述和价格)的表。我还有一个会话变量,用于存储字典中的用户选择(存储id和数量)。

我在下面制作的LINQ基本上计算了总结的一切的价值。它将表转换为字典,然后将价格乘以数量。

有更好的方法吗?

var prices = _db.MenuOptions
                .Select(o => new { o.Id, o.Price })
                .ToDictionary(o => o.Id, o => o.Price);
Session["price"] = prices
              .Where(p => orderItems.Keys.Contains((int)p.Key))
              .Sum(p => p.Value * orderItems[p.Key]);

4 个答案:

答案 0 :(得分:3)

首先想到的是循环orderItems.Keys而不是prices,然后按键过滤它们。

假设orderItems是标准字典,那么它实现IEnumerable<KeyValuePair<TKey, TValue>>。这意味着我们可以做类似的事情:

Session["price"] = orderItems.Sum(x=>x.Value*prices[x.Key]);

您可以通过连接将其全部放入一个查询中,但我个人认为它更具可读性。

除了更简洁和更易读之外,这个更好的原因是,当它只需要非常有限数量的元素时,你的原始方法将遍历所有的价格字典。实际上只有与orderItems匹配的元素。因此,当我们知道我们想要所有项目时,在较小的列表上订购会更有意义。

如果orderItems字典中的项目在价格字典中没有相应的条目,那么这只会失败,但我认为永远不会发生这种情况。如果确实如此,你需要适当保护。

答案 1 :(得分:3)

select部分是不可靠的,可以删除:

var prices = _db.MenuOptions.ToDictionary(o => o.Id, o => o.Price);

price计算可以从orderItems

开始
Session["price"] = orderItems.Sum(oi => oi.Value * prices[oi.Key]);

(假设所有orderItems在数据库中都有价格。)

编辑:从Arcturus回答,这样的事情也可能是“单行”,但可能更慢(见评论):

Session["price"] = orderItems.Sum(oi => oi.Value * _db.MenuOptions.Single(o => o.ID == oi.Key).Price);

答案 2 :(得分:3)

实际上,原始代码并不错,因为它只加载了所需的列,尽管它对所有菜单选项都这样做。

更好的解决方案是仅从数据库加载订购商品的价格:

var prices = _db.MenuOptions
                .Where(o => orderItems.Keys.Contains(o.Id))
                .Select(o => new { o.Id, o.Price })
                .ToDictionary(o => o.Id, o => o.Price);

Session["price"] = orderItems.Sum(oi => oi.Value * prices[oi.Key]);

Select语句确保仅加载ID和价格,并且无法删除。 Where语句将创建WHERE ID IN (....)子句,仅返回订单商品的价格。

答案 3 :(得分:1)

为什么首先创建一个匿名类,并将这些东西放在一个字典中,直接使用数据?

Session["price"] = _db.MenuOptions
               .Where(p => orderItems.Keys.Contains((int)p.Id))
               .Sum(p => p.Price * orderItems[p.Id]);
相关问题