【问题标题】:MVC MusicStore Artist.Name Object reference not set to an instance of an objectMVC MusicStore Artist.Name 对象引用未设置为对象的实例
【发布时间】:2015-11-20 20:59:00
【问题描述】:

通过 MVC MusicStore 学习 MVC 时让我头疼。 Model.Artist.Name for Details View page 出现此错误。

我的 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(其中 Model 是简写),但是 Model.Artist.Name 导致了我这个错误。

已解决

好的,通过在 Album 类的 Artist 和 Genre 声明中添加 virtual keyword 使其工作。但我仍然不确定会发生什么,并希望有人关心一下。

在我的相册类中,在解决之前它看起来像这样

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; }
}

通过添加Virtual关键字解决了由Genre和Artist引起的错误

    public virtual Artist Artist { get; set; }

不知何故,我仍然无法证明发生了什么,并希望了解更多信息。有人愿意解释吗?

它是这样的,Album.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")}
    }
}

【问题讨论】:

  • 调试 - 在返回 View(albums) 语句时停止。专辑长什么样?它对艺术家和流派有价值吗?
  • 是的,值是从一个类中获取的,假设代表一个数据库。
  • 您需要发布更多代码 - 您发布的内容没有任何问题,如果您在调试时弹出了 albums.Artist.Name,那么您应该不会收到您报告的错误。专辑类是什么样的?专辑呢?

标签: c# .net asp.net-mvc


【解决方案1】:

你是对的。该错误是指尚未实例化 Genre 对象和 Artist 对象,因此尝试访问其中任何一个的 Name 属性都会引发错误。

问题发生在 Find() 方法中。如果您使用的是 LinqToSql、EF、NHibernate 或类似的,请检查您的映射是否正确。

更新:

根据修改后的代码,如果您正在执行artists.Single(g =&gt; g.Name == "Test"),那么如果没有名为“Test”或其他名称的艺术家,这将引发NullReferenceException

我建议对字符串以外的其他内容进行匹配。如果可能,请使用 Id 执行匹配。这将提供更可靠的匹配条件。

理想情况下,您应该使用SingleOrDefault() 并检查是否返回了null

【讨论】:

    【解决方案2】:

    看起来ArtistNamenull

    也就是说Model 的属性Artist 没有引用Artist 的初始化实例,或者NameArtist 实例的类似场景。在尝试访问对象之前,您应该始终检查 null 值:

    if (Model.Artist != null)
    {
        //do something with artist
    }
    

    同样的解释也适用于其他属性,例如 Genre

    但奇怪的是,如果没有Artist 满足查询(或多个此类满足),则使用Single 仅获取单个实体应该引发异常 - 这是您的确切代码,还是您想要的Artist 确实存在的测试?

    【讨论】:

    • 如果 Name 属性为 null,则不会导致此错误。访问实例化对象的 Name 属性,或尝试操作 null Name 会导致此错误。
    • @Digbyswift: &lt;li&gt;Artist : &lt;%=Model.Artist.Name%&gt;&lt;/li&gt; Name。在这种情况下,我不完全确定 ASP.NET 内联脚本是否会对 null 值产生问题,但这是有可能的(默认情况下,它甚至可能在此类对象上调用 ToString。)
    • 我从假设代表数据库的模型类文件中得到了使用 Single 的那段代码。 var 艺术家 = new List {} 声明列表,然后是 new List {Title = "A Copland Celebration, Vol. I", Artist = Artists.Single(a => a.Name == "Aaron Copland & London Symphony Orchestra") } 在那里,如果它直接分配给字符串,我可以访问标题就好了。
    • 失望:但这不会导致 NullReference 异常。它只是不会在页面上显示任何内容。
    • 再次检查我的问题,我已经提交了一段模型类的代码。
    【解决方案3】:

    好的,通过在 Album 类的 Artist 和 Genre 声明中添加 virtual 关键字来使其工作。但我仍然不确定会发生什么,并希望有人关心一下。

    见上文。

    【讨论】:

    • 您正在延迟加载 Artist 和 Genre,这涉及再次返回 SQL Server,因此您实际上在这里发出 3 个请求。需要 virtual 以允许 ORM 挂钩属性并延迟加载它们,它会创建这些属性的动态代理。
    【解决方案4】:

    GenreId、ArtistId 和 AlbumId 不能为空 示例:

    public int? GenreId { get; set; }
    

    【讨论】:

      猜你喜欢
      • 2013-07-26
      • 2021-09-14
      • 2020-04-13
      • 2013-03-21
      • 2015-09-27
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多