我对我使用“分组依据”句子的 linq 产生的对象 IGrouping 有疑问。
我在数据库中有两个表,Products 和 Responses,它们的关系是 1 到 *。在 Responses 表中,我们有一个名为 FinalRate 的列,它是产品的费率。产品可以有 n 个响应或速率。
我想通过 FinalRate 的总和除以完成的费率数来获得 Products 订单。也就是说,按照平均分数从高到低的顺序排列。
因为它可以在代码中读取(在问题的末尾),所以我尝试首先获得响应。总结所有的最终比率并将它们除以我使用一个组的计数。
代码有两个问题,即使当前代码有效:
1.-我尝试在单个查询中获取产品,但这是不可能的,因为我不能使用组中的产品表,然后使用“orderby”中的响应表。另外一件事 LINQ 只让您可以对一张表进行分组,不可能有“组刺激,响应”。我无法在 LINQ 中得到这个 sql 语句:
select prod.ProductID,prod.Commercial_Product_Name,prod.Manufacturer_Name,
prod.ProductImageUrl
from rev_product prod
inner join rev_response res on res.AtProductid=prod.ProductID
group by prod.ProductID,prod.Commercial_Product_Name,prod.Manufacturer_Name
,prod.ProductImageUrl
order by (sum(res.FinalRate)/count(res.AtProductid))
我试过这个:
var gruposproductos = (from prod in ctx.Products
join res in ctx.Responses on prod.ProductID equals res.AtProductId
group prod by prod.ProductID into g
orderby (g.Sum(ra =>ra.FinalRate)/g.Count())
descending select g).Take(2);
但正如我所说,“orderby (g.Sum...”) 给出了一个错误,因为“into g”对产品表进行分组,而不是对响应表进行分组。
所以这就是为什么在我的最终代码中我没有在同一个 LINQ 语句中得到产品。
2.-一旦接受了这个事实,问题是我得到了一个 IGrouping,但是我没有得到一个响应列表,我可以在不执行代码中的两个 foreach 的情况下进行迭代。我只想要一个循环,就像你有一个“列表”对象一样。
这不是一个很酷的方法,但它确实有效。此外,我必须控制在第二个循环中只添加了 1 次。
有更好的代码吗?
var groupproducts = (from res in ctx.Responses
group res by res.AtProductId into g
orderby (g.Sum(ra =>ra.FinalRate)/g.Count())
descending select g).Take(2).ToList();
List<Product> theproducts = new List<Product>();
foreach (var groupresponse in groupproducts)
{
foreach (var response in groupresponse)
{
var producttemp= (from prod in ctx.Products
where prod.ProductID == response.AtProductId
select prod).First();
theproducts.Add(producttemp);
}
}
}
最终解决方案(非常感谢@Daniel)
var productsanonymtype = ctx.Products.Select(x => new
{
Product = x,
AverageRating = x.Responses.Count() == 0 ? 0 : x.Responses.Select(r => (double)r.FinalRate).Sum() / x.Responses.Count()
}).OrderByDescending(x => x.AverageRating);
List<Product> products = new List<Product>();
foreach (var prod in productsanonymtype)
{
products.Add(prod.Product);
}