【问题标题】:Finding Average using nested queries on another table在另一个表上使用嵌套查询查找平均值
【发布时间】:2013-08-20 00:14:04
【问题描述】:

我有一个常见问题,通过查看互联网上的几个论坛都无法解决。

我有一个使用 ASP.NET WebAPI 的餐厅评级应用程序。该应用程序有两个表餐厅和评论表。每个餐厅可能有多个评论,每个评论都有一个评分值。我试图在 WebAPI 中组合一个方法,通过查看评论表从餐厅表中提取详细信息以及每个餐厅的平均评分值。到目前为止,我的尝试是在下面的代码中,它不起作用。我尝试过使用聚合函数、平均函数、嵌套查询、连接等,但仍然无法提取平均值。如果有人可以提供帮助,我将不胜感激?

public IQueryable<RestaurantView> GetRestaurants(string All)
    {
        var query = from x in db.Restaurants
                    select new RestaurantView
                    {
                        RestaurantID = x.RestaurantID,
                        RestaurantName = x.RestaurantName,
                        RestaurantDecription = x.RestaurantDecription
                        RestaurantRatingAverage = (from a in db.Restaurants
                         join b in db.Comments on a.RestaurantID equals b.CommentsRestaurantID into z
                         from c in z
                         group c by c.CommentsRestaurantID into g
                         select new
                         {
                            RatingAverage = Convert.ToDouble(g.Average(a => a.CommentsRating))
                         };)
                    };


        return query;
    }

更新:使用 Jonathan 的技术(见下文)

public IQueryable<RestaurantView> GetRestaurants(string All)
    {
        var query = from x in db.Restaurants
                    select new RestaurantView
                    {
                        RestaurantID = x.RestaurantID,
                        RestaurantName = x.RestaurantName,
                        RestaurantDecription = x.RestaurantDecription,
                        RestaurantRatingAverage = (from a in db.Comments
                   where a.CommentsRestaurantID.Equals(x.RestaurantID)select a.CommentsRating).Average()
                    };


        return query;
    }

但我现在得到以下异常

 An error has occurred.","ExceptionMessage":"The cast to value type 'Double' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."

【问题讨论】:

  • All 的参数是什么?我没有看到它在您的代码中的任何地方使用。
  • CommentsRating 在您的RestaurantsComments 表中吗?目前你正试图从Restaurants 拉取它。
  • @King King,我现在不使用 ALL 参数,但计划在未来使用 Yes 或 No 布尔值。为混乱道歉
  • @Jonathan,CommentsRating 在 Comments 表中。看了你下面的回答,相信你已经想通了

标签: c# linq asp.net-mvc-4 asp.net-web-api


【解决方案1】:

这是一个你可以在LINQPad中执行的例子

编辑:更新以显示子查询的空值处理

void Main()
{
    var restaurants = new List<Restaurant>();
    restaurants.Add(new Restaurant(1, "McDonalds"));
    restaurants.Add(new Restaurant(2, "Wendy's"));
    restaurants.Add(new Restaurant(3, "KFC"));

    var comments = new List<Comment>();
    comments.Add(new Comment(1, 1, "I love clowns!", 9.5));
    comments.Add(new Comment(2, 1, "Disgusting", 1.0));
    comments.Add(new Comment(3, 1, "Average", 5.0));
    comments.Add(new Comment(4, 2, "Hmmm tasty", 8.5));
    comments.Add(new Comment(5, 2, "Yuck", 4.0));

    // Edit - removed comment for KFC, updated code below to handle nulls
    var restaurantsWithRatings = restaurants.Select(r => new {
            RestaurantId = r.RestaurantId,
            Name = r.Name,
            Rating = (
                comments.Where(c => c.RestaurantId == r.RestaurantId)
                    .Select(c => c.Rating)
                    .DefaultIfEmpty(0)
            ).Average()
        });

    foreach(var r in restaurantsWithRatings)
        Console.WriteLine("{0}: {1}", r.Name, r.Rating);
}

class Restaurant
{
    public Restaurant(int restaurantId, string name)
    {
        RestaurantId = restaurantId;
        Name = name;
    }

    public int RestaurantId { get; set; }
    public string Name { get; set; }
}

class Comment
{
    public Comment(int commentId, int restaurantId, string message, double rating)
    {
        CommentId = commentId;
        RestaurantId = restaurantId;
        Message = message;
        Rating = rating;
    }

    public int CommentId { get; set; }
    public int RestaurantId { get; set; }
    public string Message { get; set; }
    public double Rating { get; set; }
}

【讨论】:

  • 谢谢乔纳森!看看你的例子,我已经实现了类似的东西,我已经复制了我更新的代码作为问题的一部分,但是在返回的数据为空时仍然出现错误。平均值是 Double 类型,我尝试过 Convert.ToDouble() 但这并没有解决问题:(
  • @Piranha86 我已经更新了代码,使用 DefaultIfEmpty 应该会对你有所帮助。
猜你喜欢
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多