Reputation: 13
I'm currently working in ASP.NET with Entity Framework and I am dealing with two model objects, called "Game" and "Review".
"Review" has a property called "GameId"
"Game" has a property called "Reviews" which is an ICollection intended to hold a collection of "Review" where "GameId" matches the "Game"s "Id".
I am in the "GamesController" trying to pass a "Game" to the "Detail" view where the details of "Game" will be displayed, including the list of "Review" that match.
This is my current code.
///Controller Code///
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Game game = db.Games.Find(id);
game.Reviews = db.Reviews.ToList().Where(r => r.GameId == game.Id) as ICollection<Review>;
if (game == null)
{
return HttpNotFound();
}
return View(game);
}
///End Controller Code///
///View Code///
@model GameReviewApp.Models.Game
//snipped irrelevant code//
@foreach (var item in Model.Reviews)
{
<p>@item.Content</p>
}
///End View Code///
When running this code I get the following error when i try to load up the "Detail" page and display the list of "Review"
System.NullReferenceException: 'Object reference not set to an instance of an object.'
From what I can see, after my LINQ filter, the ICollection
isn't getting populated and it's being left null. I've double checked my database and I know there are 2 entries that should end up in the list were the filter to work properly. Any advice?
Upvotes: 1
Views: 65
Reputation: 1424
If games and reviews have a proper relationship defined, it should have been loaded by lazyloading and you don't need the second query.Otherwise just put a null check after this
Game game = db.Games.Find(id);
if (game != null)
{
game.Reviews = db.Reviews.Where(r => r.GameId == game.Id).ToList();
}
Upvotes: 0
Reputation: 1
you need to initialize game.Reviews
objGame.Reviews = new Icollection<Review>();
//or
Game objGame= new Game(){
Reviews=new ICollection<Review>()
};
Upvotes: 0
Reputation: 306
The problem is that you're trying to cast the IEnumerable returned by LINQ to an ICollection - because the cast fails, game.Reviews
will be null every time.
The below code should work for you:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Game game = db.Games.Find(id);
if (game == null)
{
return HttpNotFound();
}
game.Reviews = db.Reviews.Where(r => r.GameId == game.Id).ToList();
return View(game);
}
You can use .ToList()
instead of as ICollection<Review>
, which should successfully achieve what you're going for.
I'd also recommend removing the .ToList()
from db.Reviews.ToList()
, as it retrieves every Review
from the database and puts them in memory, and here you're only interested in Reviews
with a matching GameId
.
EDIT: As has been mentioned, your nullcheck for game
should also come immediately after resolving the object.
Upvotes: 0