简体   繁体   中英

Update the navigational property or the foreign key?

I'm using Entity Framework and I want to update a navigational property. For example, I have a Profile object and it has a navigational property to Gender . I want to change the Gender . I can update either the GenderID of the Profile object, which is the foreign key, or initialize the Gender with a new Gender object; so:

profile.GenderID = 2;

or

Profile.Gender = new Gender{ID=2, Name = "Female"};

Let's say I have a collection like Languages to represent a 1:n relationship. Do I have a list of LanguageIDs or List of Languages? How would I update the list without a hit to the DB?

If I choose the latter, what tells Entity Framework to commit either an update or an insert? Is it the primary key?

You have the following options:

1. Update the Foreign Key field in the parent object:

profile.GenderID = 2;

This has the effect of updating that field in the model, then after you call .SaveChanges(); on the context the database will be updated as will the navigation property on your object.


2. Update the navigation property directly to an EXISTING object already attached to the context:

for example:

var femaleEntity = context.Genders.First(g=>g.Name == "Female");
profile.Gender = femaleEntity;

in this instance the Navigation Property is updated right away but the .GenderId field is not updated on the profile object until you call context.SaveChanges(); whereupon EF will write the new value to the GenderId column in the database and update the .GenderId property on the profile object.


3. Update the navigation property with a NEW object:

Profile.Gender = new Gender{ID=2, Name = "Female"};

Here EF will attempt to ADD a new Gender row to the database with ID of 2 and Name = female. You almost certainly only want to do this if there is not already a 'Female' row in the Gender table of the database and if the Gender ID is an identity allocated by the database it will be overwritten with the allocated value upon calling .SaveChanges().


Ignoring the subtleties about when our objects are updated by EF, the first 2 options are roughly equivalent* but the 3rd option has a different behavior. It is up to us to know (or to determine) whether we need to link to an existing Gender object or to add a new one to the data store.

Exactly the same principle applies to your 1:Many relationships too:

profile.Languages = new List<Languages>
{
    new Language{Name = "Spanish"}
}

creates a new row in the languages table, whereas:

var spanish = context.Languages.First(l=>l.Name == "Spanish");
profile.Languages = new List<Languages>
{
    spanish
}

finds the existing row with name 'Spanish' then updates the navigational property.

If you have a list of language ids stored in a variable you want to update the navigation property with the associated language objects you could do:

var languagesToAdd = context.Languages.Where(l=>languageIds.Contains(l.ID)).ToList();
profile.Languages = languagesToAdd;

*Of course there is a performance penalty with option 2 if you don't already have an attached Gender object in memory because fetching the data, for example, by calling .First() as in my example, would (of course) need another round trip to the database.

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