Updating disconnected objects with many-to-many relationships

Suppose I have the following model classes in the First-Framework Framework-First setup:

public class Person { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Team> Teams { get; set; } } public class Team { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Person> People { get; set; } } 

The database created from this code includes a TeamPersons table representing relationships between many people and teams between many.

Now suppose that I have a disabled Person object (not a proxy server and not yet context bound) whose team collections contain one or more disabled Team objects, all of which are commands already in the database. An object, for example, will be created as follows, for example, if a Person with identifier 1 and a command with Id 3 already existed in db:

 var person = new Person { Id = 1, Name = "Bob", Teams = new HashSet<Team> { new Team { Id = 3, Name = "C Team"} } }; 

What is the best way to update this object so that after the update, the TeamPersons table contains one row for Bob, linking it to the C Team? I tried the obvious:

 using (var context = new TestContext()) { context.Entry(person).State = EntityState.Modified; context.SaveChanges(); } 

but the collection of commands is simply ignored. I have also tried different things, but it seems nothing like what I am doing here. Thanks for any help.

EDIT:

So, I get that I could get both the identity and the [s] command from db, update them and then commit the changes:

 using (var context = new TestContext()) { var dbPerson = context.People.Find(person.Id); dbPerson.Name = person.Name; dbPerson.Teams.Clear(); foreach (var id in person.Teams.Select(x => x.Id)) { var team = context.Teams.Find(id); dbPerson.Teams.Add(team); } context.SaveChanges(); } 

It is a pain if Person is a complex entity. I know that I could use Automapper or something to make things a little easier, but still it seems a shame if there is no way to save the original person object, instead of getting a new one and copying all the properties on top ...

+8
c # entity-framework many-to-many dbcontext ef-code-first
source share
4 answers

The general approach is to extract Team from the database and Add to the Person Teams collection. The EntityState.Modified setting EntityState.Modified affects scalar properties, not navigation properties.

+1
source share

First try to select existing entities, and then join the team to a collection of collections of character objects.

Something like this: (the syntax may not be entirely accurate)

 using (var context = new TestContext()) { var person = context.Persons.Where(f => f.Id == 1).FirstOrDefault(); var team = context.Teams.Where(f => f.Id == 3).FirstOrDefault(); person.Teams.Add(team); context.Entry(person).State = EntityState.Modified; context.SaveChanges(); } 
0
source share

This is where EF s ** ks. very inefficient for a disabled scenario. uploading data for updating / deleting and updating each for reconnecting, you can’t just bind the updated object to the context, since an entity with the same key can already exist in the context, in which case EF will simply start. what needs to be done is to check if the object with the same key is already in context and is bound or updated accordingly. it is worse to update an object with many to many relationships. removal of the removed child occurs from a set of child entities, but not for the reference property, it is very dirty.

0
source share

You can use the Attach method. Try the following:

 using (var context = new TestContext()) { context.People.Attach(person); //i'm not sure if this foreach is necessary, you can try without it to see if it works foreach (var team in person.Teams) { context.Teams.Attach(team); } context.Entry(person).State = EntityState.Modified; context.SaveChanges(); } 

I have not tested this code, let me know if you have problems.

0
source share

All Articles