简体   繁体   中英

Entity Framework Lazy Loading Does Not Work

I am migrating my project from EF 4.0 to EF 6.0. I am trying to get properties from navigated entity after insert new entity. That code runs without any problem in EF 4.0 but when I try to run in EF 6.0 I am gettin NullReference Exception.

User Entity:

public partial class users
{
    public int RID { get; set; }
    public string Name { get; set; }
    public Nullable<int> LangRef { get; set; }

    public virtual language language { get; set; }
}

Language Entity:

public partial class language
{
    public language()
    {
        this.users = new HashSet<users>();
    }

    public int RID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<users> users { get; set; }
}

Test Code:

test1Entities testEnt = new test1Entities();
users user = new users();
user.Name = "asd";
user.LangRef = 1;//That ID refer to English record in Language entity
testEnt.users.Add(user);
testEnt.SaveChanges();

string lang = user.language.Name;//Should return "English". However language property seem null

Model:

模型:

You say that user.language.Name should return English, you are not setting that anywhere. You have to set the language when you create a new user.

test1Entities testEnt = new test1Entities();
users user = new users();
user.Name = "asd";
user.LangRef = 1;

// grab the english language entity from the database
language englishLanguage = entities.First(o => o.Name == "English");

// set the users language to english
user.language = englishLanuage;

testEnt.users.Add(user);
testEnt.SaveChanges();

Imagine if you were inserting a user with raw SQL, you would run something like this

INSERT INTO users (name, languageId) VALUES ('Foo', 1);

Where 1 is the RID of the record in the language table which maps to the english language. The 1 is a Foreign Key in the users table which maps a user to their language. Same as with the raw SQL you must explicitly tell Entity Framework which language the user has. This is done by querying the DbContext for the language (which returns a tracked entity), then setting that entity to the navigation property.


Alternatively, if you know the primary key of the language record in advance, you can create a new language entity (with the correct RID) and attach it to the DbContext, then set it to the navigation property. This would make it so there is one less query against the database. While this would be a little more effecient, you should do whatever is easier/makes the most sense to you. Get it working, then you can optimize bottlenecks later.

language englishLanguage = new language() { RID = 1, Name = "English" };
testEnt.languages.Attach(language);

user.language = englishLanguage;
testEnt.users.Add(user);

Edit

Given your recent edits, it is now more clear what you are trying to do. I didn't realize that LangRef was your foreign key since it was a decimal and doesn't follow normal naming conventions.

The solution is described in this answer, https://stackoverflow.com/a/18251442/1160036 . The problem arises from Entity Framework caching. After SaveChanges() (so that the RID is updated), you can detach and re-pull the user to refresh it.

testEnt.users.Add(user);
testEnt.SaveChanges();
((IObjectContextAdapter)testEnt).ObjectContext.Detach(user);
users user = testEnt.First(o => o.RID == user.RID);
Console.WriteLine(user.language.Name);

Opening a new DbContext works as well, but this does cause another connection to be made to the database.

As described in the above answer, testEnt.Entry<users>(user).Reload() unfortunately doesn't work.

Instead of using new users() try testEnt.users.Create() . The difference is that the object returned will be a proxy class which is needed for lazy loading of navigation properties.

As an aisde, doing the opposite and setting the language navigation property itself and not the LangRef foreign key value should actually correctly set the LangRef property when you call SaveChanges() .

See DbSet.Create method on MSDN.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM