以下查询确实解决了我的问题,但它似乎过于复杂。
问题是我有一个存储菜单选项(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]);
答案 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]);