Johnson Duru
Johnson Duru

Reputation: 682

how to Use select many in lambda expression mvc

i have the following lambda expression in MVC application.i want to group data.

 var toprating=  _db.Movie.SelectMany(m => m.Rating.Select(r=> new 

            {

           movieID=r.MovieID,
           MovieTitle= m.Title
            })).GroupBy(m=>m.movieID).ToList();

      ViewBag.TopMovie = toprating;
        }

i want to pass this to my view. i try writing the following in my view

 IEnumerable<Movie> TopMovies = ViewBag.TopMovie;

but got this error

Cannot implicitly convert type 'object' to 'System.Collections.Generic.IEnumerable<Movie>'. An explicit conversion exists (are you missing a cast?)

any help will be appriciated.

Upvotes: 1

Views: 9622

Answers (3)

Timwi
Timwi

Reputation: 66573

The type of the collection that you are passing in isn’t an IEnumerable<Movie>. Notice you are using an anonymous type, and then you’re also using GroupBy. The resulting type is complex.

Your query is also meaningless because you’re accessing Rating but not using it, so you probably end up with multiple copies of the same movie, and with all the rating information discarded. For the moment I’ll assume you actually want the ratings included.

So you could use the following query, for example:

ViewBag.Ratings = _db.Movie.SelectMany(m => m.Rating.Select(r => new 
{
    Movie = m,
    Rating = r
})).GroupBy(m => m.Movie, m => m.Rating).ToList();

Now the type of the above query is List<IGrouping<Movie, Rating>>, so you can use that in your view:

List<IGrouping<Movie, Rating>> ratings = ViewBag.Ratings;

Upvotes: 2

Leniency
Leniency

Reputation: 5024

It is because of the anonymous object in your SelectMany as well as the GroupBy.

GroupBy does not return an IEnumerable, but rather IEnumerable<IGrouping<TKey, TSource>> - essentially a collection of collections where each sub collection has the same key value.

In the case you have, grouping by the movie Id is going to give you a rather strange collection:

toprating: [
    [
       // MovieID, Movie Title
        { 1, Movie1Title },   // one Id/title pair for every rating.
        { 1, Movie1Title },
        { 1, Movie1Title },
        ...
    ],
    [
        { 2, Movie2Title },   // one title for every rating.
        { 2, Movie2Title },
        { 2, Movie2Title },
        ...
    ]
]

Something like that, but if that's really what you want, okay. Then in your view, you're trying to do this:

IEnumerable<Movie> TopMovies = ViewBag.TopMovie;

But TopMovie is IEnumerable<IGrouping<int, object>>. So of course it can't be cast to a Movie.

This will give you the object and allow you enumerate over it:

IEnumerable<IGrouping<int, object>> TopMovies = ViewBag.TopMovie;

I suspect though that this isn't what you're actually wanting to do, but I can't help without more information.

Upvotes: 0

Kasper Holdum
Kasper Holdum

Reputation: 13363

The ViewBag is a dynamic object (a feature introduced with .NET 4.0) and thus .NET does not know what type any of the properties on the object is. Since .NET is not aware of the type, you must explicitly cast any properties on the ViewBag if you want to store them in a variable.

 var topMovies = ViewBag.TopMovie as IEnumerable<Movie>;

And to convert anything to the type of Movie you will need to change your original LINQ query to select Movies and not anonymous types.

Upvotes: 3

Related Questions