Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating disconnected entities with many-to-many relationships

Suppose I have the following model classes in an Entity Framework Code-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 the many-to-many relationship between people and teams.

Now suppose I have a disconnected Person object (not a proxy, and not yet attached to a context) whose Teams collection contains one or more disconnected Team objects, all of which represent Teams already in the database. An object such as would be created by the following, just for example, if a Person with Id 1 and a Team with Id 3 already existed in the 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 of updating this object, so that after the update the TeamPersons table contains a single row for Bob, linking him to C Team ? I've tried the obvious:

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

but the Teams collection is just ignored by this. I've also tried various other things, but nothing seems to do exactly what I'm after here. Thanks for any help.

EDIT:

So I get that I could fetch both the Person and the Team[s] from the db, update them and then commit 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();
}

This is a pain if Person's a complicated entity, though. I know I could use Automapper or something to make things a bit easier, but still it seems a shame if there's no way of saving the original person object, rather than having to get a new one and copy all the properties over...

like image 451
Duncan Avatar asked Nov 15 '12 20:11

Duncan


People also ask

What's a recommended approach for using EF in disconnected applications?

Following are the two steps that needs to be taken with disconnected entity graph or even a single disconnected entity. Attach entities with the new context instance and make context aware about these entities. Set appropriate EntityStates to these entities manually.

Which of the following updates a disconnected entity to the database EF core?

Entity Framework Core introduced the DbContext. Update() method which attaches the specified entity to a context and sets its EntityState to Modified. Alternatively, you can also use the DbSet.

What is disconnected scenario in Entity Framework?

Disconnected scenario is when an entity is retrieved from the database and modified in the different context. Let's suppose we want to display some data in a Presentation Layer and we are using some n-tier application, so it would be better to open the context, fetch the data and finally close the context.


Video Answer


1 Answers

The general approach is to fetch the Team from the database and Add that to the Person's Teams collection. Setting EntityState.Modified only affects scalar properties, not navigation properties.

like image 191
Gert Arnold Avatar answered Sep 28 '22 03:09

Gert Arnold