NullReferenceException while trying to including a

2019-08-02 14:13发布

问题:

Framework: I'm using using MVC 3 + EntityFramework 4.1 Code-First.

Concept: One Legislation entity has many Provision entities. The idea is that the user enters a Legislation entity, that gets saved then the function that saves it passes it along to another function to see whether that Legislation has a ShortTitle. If it does, then it formats it into a properly worded string and includes it as the Legislation's first Provision, then saves the changes to db.

Issue: The problem is, I've tried coding it in different ways, I keep getting a NullReferenceException, telling me to create a new object instance with the "new" keyword, and points me to the savedLegislation.Provisions.Add(provision); line in my second function.

Here are the two functions at issue, this first one saves the Legislation proper:

public Legislation Save(NewLegislationView legislation)
{
    Legislation newLegislation = new Legislation();
    // Simple transfers
    newLegislation.ShortTile = legislation.ShortTile;
    newLegislation.LongTitle = legislation.LongTitle;
    newLegislation.BillType = legislation.BillType;
    newLegislation.OriginatingChamber = legislation.OriginatingChamber;
    newLegislation.Preamble = legislation.Preamble;

    // More complicated properties
    newLegislation.Stage = 1;
    this.NumberBill(newLegislation); // Provides bill number
    newLegislation.Parliament = db.LegislativeSessions.First(p => p.Ending >= DateTime.Today);
    newLegislation.Sponsor = db.Members.Single(m => m.Username == HttpContext.Current.User.Identity.Name);

    // And save
    db.Legislations.Add(newLegislation);
    db.SaveChanges();

    // Check for Short titles
    this.IncludeShortTitle(newLegislation);

    // return the saved legislation
    return newLegislation;
}

And the second function which is invoked by the first one deals with checking whether ShortTitle is not empty and create a Provision that is related to that Legislation, then save changes.

public void IncludeShortTitle(Legislation legislation)
{
    var savedLegislation = db.Legislations.Find(legislation.LegislationID);
    if (savedLegislation.ShortTile.Any() && savedLegislation.ShortTile.ToString().Length >= 5)
    {
        string shortTitle = "This Act may be cited as the <i>" + savedLegislation.ShortTile.ToString() + "</i>.";
        var provision = new Provision()
        {
            Article = Numbers.CountOrNull(savedLegislation.Provisions) + 1,
            Proponent = savedLegislation.Sponsor,
            Text = shortTitle
        };
        savedLegislation.Provisions.Add(provision);
        db.SaveChanges();
    }
}

I've been researching how SaveChanges() works and whether it is properly returning the updated entity, it does (since I get no issue looking it up in the second function). If it works properly, and the legislation is found and the provision is newly created in the second function, I don't see what is the "null" reference it keeps spitting out.

回答1:

The null reference in this case would be savedLegislation.Provisions. The Provisions collection won't be initialized to a new List<Provision> when EF returns your Legislation instance from the db.Legislations.Find(...) method.

The first thing I'd try is something like this:

var savedLegislation = db.Legislations
    .Include("Provisions")
    .First(l => l.LegislationID == legislation.LegislationID);

... but I'd also consider just using the legislation instance that was passed into the method rather than fetching it from the database again.