Cannot update many-to-many relationships in Entity Framework

I am using Entity Framework 4.3 Code First and I have a problem updating many-to-many relationships.

I have defined the following classes:

public abstract class Entity { [Column(Order = 0)] [Key] public int Id { get; set; } [Timestamp] [Column(Order = 1)] public byte[] Version { get; set; } } public class Video : Entity { public string Title { get; set; } public string Description { get; set; } public TimeSpan Length { get; set; } public virtual ICollection<Coworker> Coworkers { get; set; } } public class Coworker : Entity { public string FirstName { get; set; } public string LastName { get; set; } public virtual ICollection<Video> Videos { get; set; } } 

When the database is created, the scheme looks right: There is also a table “Video”, “Colleagues” and “Video encoders”, without

I use the repository template in the N-Tier application to access the database, my Insert and Update method looks like this:

 public T Insert(T entity) { //Creates database context. When it disposes, it calls context.SaveChanges() using (var session = new DatabaseSession()) { session.Context.Set<T>().Add(entity); } } public T Update(T entity) { //Creates database context. When it disposes, it calls context.SaveChanges() using (var session = new DatabaseSession()) { entity = session.Context.Set<T>().Attach(entity); session.Context.Entry(entity).State = EntityState.Modified; } return entity; } 

When I update an object, I create an entity object from DTO, so use DbSet.Attach instead of selecting it and updating the properties one by one.

When I initialize the database, I add some test data:

  • Create 3 Colleagues where I give the first and last name. (A, B, C)
  • Create 3 videos where I set the name, description and length, and also set a few employees. The first video has A, B, the second has B, C and the third has A, C.

When I list the video from the code, I see that the Video.Coworkers collection is filled with good values, and when I query the reference table (VideoCoworkers) in SQL Server Management Studio, it also looks good.

My problem is when I update, for example, the name of the video, it works. But when I try to remove existing employees (B and C) from Video2 and try to add employee A, then the connection will not be updated. It also does not work when I am only trying to add a new employee or trying to delete him. I create an object that is used as a parameter of the Update () method, creating a new Video object with a new collection of Coworkers (which are selected from the database using the Find () method by identifier).

What is the correct way to update many-to-many relationships?

+6
source share
3 answers

But when I try to remove existing employees (B and C) from Video2, and try to add colleague A, then the connection will not be updated.

Without using a shared repository, the correct procedure is:

 using (var session = new DatabaseSession()) { video2 = session.Context.Set<Video>().Include(v => v.Coworkers) .Single(v => v.Id == video2Id); coworkerA = new Coworker { Id = coworkerAId }; session.Context.Set<Coworker>().Attach(coworkerA); video2.Coworkers.Clear(); video2.Coworkers.Add(coworkerA) session.Context.SaveChanges(); } 

The essential part is that you must load or attach the object to its original state, change the object, i.e. delete and add children, and then save the changes. Change Detection EF will create the necessary INSERT and DELETE statements for the link table entries. The simple procedure for setting the Modified state that you are trying to use in your general Update method is suitable only for updating scalar properties - for example, for changing the title of a video, but it will not work for updating relations between objects.

+6
source

To solve this problem:

  • snap object to context
  • upload collection (collection not loaded because)
  • change object state to changed
  • save changes

So your upgrade code should look like this:

 public Video Update(Video entity) { //Creates database context. When it disposes, it calls context.SaveChanges() using (var session = new DatabaseSession()) { entity = session.Context.Set<Video>().Attach(entity); session.Context.Entry(entity).Collection(p => p.Coworkers).Load(); session.Context.Entry(entity).State = EntityState.Modified; } return entity; } 
+2
source

Please refer here to learn how to save basic information in asp.net mvc with a database. Hope this gives you an idea of ​​the code. You can also see an example of knokout.js

-1
source

Source: https://habr.com/ru/post/914503/


All Articles