Reputation: 279
I am trying to make a suggestion system on my restaurant review site. It gets the average score of all reviews of a certain restaurant and then finds the average review score from all of the other restaurants that have the same cuisine as the original restaurant. It returns a list of restaurants with the same cuisine that have a greater review average than the original restaurant. It then saves the list to the database.
I have tried to create the query in linq but I keep on recieving errors such as Cannot implicitly convert type 'System.Collections.Generic.List<int>' to 'int'
or the results of the query are wrong.
Any help would be greatful.
Error Line
var getrestaurantaverage = db.Reviews
.Where(r => r.RestaurantId = getrestaurantsid)
.Average(r => r.score);
Suggestion Function
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");
Upvotes: 0
Views: 126
Reputation: 112342
.Where(r => r.RestaurantId = getrestaurantsid)
tries to compare an int
id with a list. If you want to find resturants whose IDs are in the list, do this:
var getrestaurantaverage = db.Reviews
.Where(r => getrestaurantsid.Contains(r.RestaurantId))
.Average(r => r.score);
To get the average of each individual restaurant, you could create an anonymous type
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);
}
This gives you the average per restaurant ID.
However there is no need to get a list of restaurant ids beforehand, do it directly
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) });
Upvotes: 1
Reputation: 203816
So the problem with your code is right here:
.Where(r => r.RestaurantId = getrestaurantsid)
getrestaurantsid
is a list of values not one value.
We can change this, but your problems are more significant. getrestaurantaverage
cannot be just one query, with your general approach, you need to do it, *for each id in getrestaurantsid
:
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();
}
}
But this is super inefficient. You're now executing lots and lots of different DB queries. We can simplify this whole thing a lot.
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);
And that's it. One single DB query, and only a few lines of code.
Upvotes: 1
Reputation: 125620
Seems like you're making far too many DB calls to get all necessary data. You should probably try to merge all these queries into one:
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
Upvotes: 2
Reputation: 19635
Your issue is here:
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 is of type List<int>
, so the expression in the Where
function below it is not going to work.
I suggest something more like this:
var getrestaurantaverage = db.Reviews.Where(r => getrestaurantsid.Contains(r.RestaurantId)).Average(r => r.score);
Upvotes: 0