【问题标题】:Return a list of averages LINQ返回平均 LINQ 列表
【发布时间】:2014-03-05 18:28:15
【问题描述】:

我正在尝试在我的餐厅评论网站上提出建议系统。它获取某个餐厅的所有评论的平均分数,然后从与原始餐厅具有相同美食的所有其他餐厅中找到平均评论分数。它返回一个具有相同美食且平均评价高于原始餐厅的餐厅列表。然后它将列表保存到数据库中。

我尝试在 linq 中创建查询,但我不断收到错误消息,例如 Cannot implicitly convert type 'System.Collections.Generic.List<int>' to 'int' 或查询结果错误。

任何帮助都会很棒。

错误线

var getrestaurantaverage = db.Reviews
    .Where(r => r.RestaurantId = getrestaurantsid)
    .Average(r => r.score);

建议功能

var averagescore = db.Reviews
    .Where(r => r.RestaurantId == review.RestaurantId)
    .Average(r => r.score);

var getrestaurantsid = (from r in db.Reviews
                       where r.Cuisine == review.Cuisine
                       select r.RestaurantId).ToList();
var getrestaurantaverage = db.Reviews
    .Where(r => r.RestaurantId = getrestaurantsid)
    .Average(r => r.score);

var choices = (from r in db.Reviews
               where getrestaurantaverage >= averagescore
               select r.RestaurantId).ToList();
foreach (var item in choices)
{
    var suggestion = new Suggestion()
    {
        reviewid = review.id,
        Userid = review.UserId,
        restaurantid = item
    };
    db.Suggestions.Add(suggestion);
    db.SaveChanges();
}

return RedirectToAction("Index", "Review");

【问题讨论】:

  • 哪一行给你一个错误?

标签: c# asp.net sql asp.net-mvc linq


【解决方案1】:

似乎您进行了太多的数据库调用来获取所有必要的数据。您可能应该尝试将所有这些查询合并为一个:

from r in db.Reviews
where r.Cuisine == review.Cuisine
group r by r.RestaurantId into g
where g.Average(x => x.Score) >= db.Reviews.Where(r => r.RestaurantId == review.RestaurantId).Average(x => x.Score)
select g.Key

【讨论】:

  • +1 因为这个查询比我的要好一些。我不会简单地删除我的答案,因为这个答案没有解释为什么 OP 的代码不起作用。
【解决方案2】:

.Where(r => r.RestaurantId = getrestaurantsid) 尝试将int id 与列表进行比较。如果您想查找 ID 在列表中的餐厅,请执行以下操作:

var getrestaurantaverage = db.Reviews
    .Where(r => getrestaurantsid.Contains(r.RestaurantId))
    .Average(r => r.score);

要获得每个餐厅的平均值,您可以创建一个匿名类型

var getrestaurantaverage = db.Reviews
    .Where(r => getrestaurantsid.Contains(r.RestaurantId))
    .GroupBy(r => r.RestaurantId)
    .Select(g => new { ID = g.Key, Average = g.Average(r => r.score) });

foreach (var x in getrestaurantaverage) {
    Console.WriteLine("Restaurant = {0}, average = {1}", x.ID, x.Average);
}

这会为您提供每个餐厅 ID 的平均值。


不过不需要事先获取餐厅id列表,直接做吧

var getrestaurantaverage = db.Reviews
    .Where(r => r.Cuisine == review.Cuisine)
    .GroupBy(r => r.RestaurantId)
    .Select(g => new { ID = g.Key, Average = g.Average(r => r.score) });

【讨论】:

  • 将为您提供所有餐厅的平均值。
  • 列表getrestaurantsid 中包含的所有餐厅,因为Average 获得了一个由前面的Where 过滤的枚举。
  • 如何获得每家餐厅的平均值?
【解决方案3】:

所以你的代码的问题就在这里:

.Where(r => r.RestaurantId = getrestaurantsid)

getrestaurantsid 是一个值列表而不是一个值。

我们可以改变这一点,但您的问题更为严重。 getrestaurantaverage不能只是一个查询,用你的一般方法,你需要这样做,*对于getrestaurantsid中的每个id:

foreach var restaurantID in getrestaurantsid)
{
    var getrestaurantaverage = db.Reviews.Where(r => r.RestaurantId = getrestaurantsid).Average(r => r.score);

    var choices = (from r in db.Reviews
                   where getrestaurantaverage >= averagescore
                   select r.RestaurantId).ToList();
    foreach (var item in choices)
    {
        var suggestion = new Suggestion()
        {
            reviewid = review.id,
            Userid = review.UserId,
            restaurantid = item
        };
        db.Suggestions.Add(suggestion);
        db.SaveChanges();
    }

}

但这是超级低效的。您现在正在执行 lotslots 的不同数据库查询。我们可以将整个事情简化很多很多

var reviewAverages = db.Reviews.Where(r => r.Cuisine == review.Cuisine)
    .GroupBy(r => r.RestaurantId)
    .ToDictionary(group => group.Key, group => group.Average(r => r.score);

var myAverage = reviewAverages[review.RestaurantId];
var choices = reviewAverages.Where(pair => pair.Value >= myAverage);

就是这样。一个数据库查询,只需几行代码。

【讨论】:

  • 不检查 Cuisine 是否相等。当您也可以在 DB 上制作 >= myAverage 时,还将获得所有应用程序的平均值。
【解决方案4】:

您的问题在这里:

var getrestaurantsid = (from r in db.Reviews
                       where r.Cuisine == review.Cuisine
                       select r.RestaurantId).ToList();
var getrestaurantaverage = db.Reviews.Where(r => r.RestaurantId = getrestaurantsid).Average(r => r.score);

getrestaurantsid 的类型为 List<int>,因此它下面的 Where 函数中的表达式不起作用。

我建议更像这样:

var getrestaurantaverage = db.Reviews.Where(r => getrestaurantsid.Contains(r.RestaurantId)).Average(r => r.score);

【讨论】:

  • 将为您提供所有餐厅的平均值。
  • @MarcinJuraszek 我认为这就是 OP 想要的。
  • @BrianDriscoll 不,他正在寻找所有餐厅的平均水平高于给定餐厅。他需要每家家餐厅的平均值,这是该特定查询要获取的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-10
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多