我目前正在ASP.NET中使用Entity Framework,我正在处理两个模型对象,称为“Game”和“Review”。
“评论”有一个名为“GameId”的属性
“游戏”有一个名为“评论”的属性,这是一个ICollection,旨在保存“评论”的集合,其中“GameId”与“游戏”的“Id”匹配。
我在“GamesController”中尝试将“游戏”传递到“详细信息”视图,其中将显示“游戏”的详细信息,包括匹配的“评论”列表。
这是我目前的代码。
///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///
运行此代码时,当我尝试加载“详细信息”页面并显示“评论”列表时出现以下错误
System.NullReferenceException:'对象引用未设置为对象的实例。'
从我所看到的情况来看,在我的LINQ过滤器之后,ICollection
没有被填充并且它被保留为空。我已经仔细检查了我的数据库,我知道列表中最后有两个条目是过滤器才能正常工作。有什么建议吗?
答案 0 :(得分:0)
问题是您正在尝试将LINQ返回的IEnumerable转换为ICollection - 因为转换失败,game.Reviews
每次都将为null。
以下代码应该适合您:
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);
}
您可以使用.ToList()
代替as ICollection<Review>
,这应该可以成功实现您的目标。
我还建议从.ToList()
中删除db.Reviews.ToList()
,因为它会从数据库中检索每个Review
并将它们放入内存中,此处您只需要对Reviews
感兴趣且匹配GameId
。
编辑:如前所述,game
的空检查也应在解析对象后立即进行。
答案 1 :(得分:0)
你需要初始化game.Reviews
objGame.Reviews = new Icollection<Review>();
//or
Game objGame= new Game(){
Reviews=new ICollection<Review>()
};
答案 2 :(得分:0)
如果游戏和评论定义了正确的关系,它应该已经通过延迟加载加载,你不需要第二个查询。否则只需在此之后进行空检查
Game game = db.Games.Find(id);
if (game != null)
{
game.Reviews = db.Reviews.Where(r => r.GameId == game.Id).ToList();
}