开发者

MVC MusicStore Artist.Name Object reference not set to an instance of an object

Cracking my head while learning MVC through MVC MusicStore . Got this error for Model.Artist.Name for Details View page .

My Storecontroller Details method should be fine .

    public ActionResult Details(int id)
    {
        //returns and albums searched from the id 
        var albums = storeDB.Albums.Find(id);
        return View(albums);
    }

And this is how I output the view

    <li>Price : <%=Model.Price %></li>
    <li>Artist : <%=Model.Artist.Name%></li>

Works fine for the price , and it only show error for Model.Genre.Name and Artist.Name . I am suspecting the declaration for th开发者_如何转开发ese properties in sampledata.cs caused this issue

    Artist = artists.Single(a => a.Name == "Aaron Copland & London Symphony Orchestra")

But my knowledge of this is too weak to make up anything . Please help .

Alright , the value is fetched from a class file looking like this

    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")}
        }
    }

Take notice on how the value are being assigned , I can access Model.Title fine (where Model as the short hand) , but Model.Artist.Name caused me that error .

Solved

Alright , got it to work by adding virtual keyword to the Artist and Genre declaration in Album class . But I am still not sure what happens and would like to have anyone care to shed some lights .

In my Album class , before it is solved it looks like this

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

The error caused by Genre and Artist is solved by adding Virtual keyword

    public virtual Artist Artist { get; set; }

Somehow , I still couldn't justify what happens and wish to learn more . Anyone care to explain ?

It goes like this , 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; }
    }
}

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

    }
}

and implemented in 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);
    }

Finally the sample data

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")}
    }
}


You are right. The error is referring to the fact that the Genre object and the Artist object has not been instantiated, and so attempting to access the Name property of either is throwing the error.

The issue is happening within the Find() method. If you are using LinqToSql, EF, NHibernate or simliar, check that your mapping is correct.

Update:

Based on the revised code, if you are doing a artists.Single(g => g.Name == "Test") then this will would throw a NullReferenceException if there is no Artist with the name "Test" or whatever.

I would advise doing the match on something other than a string. Use an Id to perform the match if possible. This will provide a much more reliable match condition.

Ideally you should use SingleOrDefault() and check whether null is returned.


It looks that Artist or Name is null.

That is to say the property Artist of Model does not have a reference to an initialised instance of an Artist, or a likewise scenario for Name of an Artist instance. You should always check for null values prior to attempting to access an object:

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

The same explanation would stand for other properties, such as Genre, too.

Curiously, though, is that the use of Single to get only an individual entity ought to throw an exception if no Artist satisfies the query (or more than one of such satisfies) - is this your exact code, or a test that the Artist you want does actually exist?


Alright , got it to work by adding virtual keyword to the Artist and Genre declaration in Album class . But I am still not sure what happens and would like to have anyone care to shed some lights .

See above .


GenreId,ArtistId and AlbumId cannot be null example:

public int? GenreId { get; set; }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜