MVC MusicStore Artist.Name对象引用未设置为对象的实例
本文关键字:对象 实例 设置 MusicStore Artist Name 对象引用 MVC | 更新日期: 2023-09-27 17:59:30
通过MVC MusicStore学习MVC时,我的头都碎了。"Model.Artist.Name for Details View"页面出现此错误。
My Storecontroller Details方法应该可以。
public ActionResult Details(int id)
{
//returns and albums searched from the id
var albums = storeDB.Albums.Find(id);
return View(albums);
}
这就是我输出视图的方式
<li>Price : <%=Model.Price %></li>
<li>Artist : <%=Model.Artist.Name%></li>
对于这个价格来说,效果很好,它只显示Model.Genre.Name和Artist.Name的错误。我怀疑sampledata.cs中这些属性的声明导致了这个问题
Artist = artists.Single(a => a.Name == "Aaron Copland & London Symphony Orchestra")
但我对这方面的知识太薄弱,无法弥补。请帮忙。
好吧,这个值是从一个类文件中提取的,看起来像这个
protected override void Seed(MusicStoreEntities context)
{
var artists = new List<Artist>
{
new Artist { Name = "Aaron Copland & London Symphony Orchestra" },
etcetc
}
new List<Album>
{
new Album { Title = "ABC", Artist= artists.Single(g => g.Name == "Test")}
}
}
注意值是如何分配的,我可以访问Model.Title fine(其中Model是简写),但Model.Artist.Name导致了这个错误。
已解决
好吧,通过在Album类的Artist和Genre声明中添加虚拟关键字,就可以开始工作了。但我仍然不确定会发生什么,我希望有人能关心一下。
在我的相册类中,在解决之前,它看起来像这个
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public int ArtistId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string AlbumArtUrl { get; set; }
public Genre Genre { get; set; }
public Artist Artist { get; set; }
}
通过添加虚拟关键字解决了由流派和艺术家引起的错误
public virtual Artist Artist { get; set; }
不知怎的,我仍然无法证明发生了什么,我希望了解更多。有人想解释一下吗?
它是这样的,相册.cs
namespace MvcMusicStore.Models
{
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public int ArtistId { get; set; }
public string Title { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}
}
使用EF MusicStore.cs
namespace MvcMusicStore.Models
{
//represent entity framework , handle create ,read , update and del ops
public class MusicStoreEntities : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
}
}
并在StoreController.cs 中实现
MusicStoreEntities storeDB = new MusicStoreEntities();
public ActionResult Details(int id)
{
//returns and albums searched from the id
var albums = storeDB.Albums.Find(id);
return View(albums);
}
最后是样本数据
protected override void Seed(MusicStoreEntities context)
{
var artists = new List<Artist>
{
new Artist { Name = "Aaron Copland & London Symphony Orchestra" },
etcetc
}
new List<Album>
{
new Album { Title = "ABC", Artist= artists.Single(g => g.Name == "Test")}
}
}
你说得对。该错误指的是Genre对象和Artist对象尚未实例化,因此试图访问其中任何一个的Name属性都会引发错误。
问题发生在Find()方法中。如果您使用的是LinqToSql、EF、NHibernate或simliar,请检查映射是否正确。
更新:
根据修改后的代码,如果你正在进行artists.Single(g => g.Name == "Test")
,那么如果没有名为"Test"或其他名称的艺术家,这将抛出NullReferenceException
。
我建议用绳子以外的东西来比赛。如果可能,请使用Id进行匹配。这将提供更加可靠的匹配条件。
理想情况下,您应该使用SingleOrDefault()
并检查是否返回了null
。
看起来Artist
或Name
就是null
。
也就是说,Model
的属性Artist
不具有对Artist
的初始化实例的引用,或者对Artist
实例的Name
的类似场景的引用。在尝试访问对象之前,您应该始终检查null
值:
if (Model.Artist != null)
{
//do something with artist
}
同样的解释也适用于其他属性,例如Genre
。
然而,奇怪的是,如果没有Artist
满足查询(或不止一个满足查询),那么使用Single
只获取单个实体应该抛出异常吗?这是你的确切代码,还是你想要的Artist
确实存在的测试?
好吧,通过在Album类中的Artist和Genre声明中添加虚拟关键字来实现它。但我仍然不确定会发生什么,我希望有人能关心一下。
请参见上文。
GenreId、ArtistId和AlbumId不能为空示例:
public int? GenreId { get; set; }