简体   繁体   中英

Why does Entity Framework add a related record even if it already exists in the database?

Why does Entity Framework add a related record even if it already exists in the database? It should just update the junction table in this case)?

I am working with Entity Framework 6, I have a many-to-many relationship between Directors and Movies . I want to post a new movie using a Dto called MovieUpdateDto . Movie class has a property of type ICollection<Directors> Directors .

The json that represents the Dto looks like this:

{
    "Name": "new movie",
    "Description": "new movie Description",
    "Price": 1000.0,
    "Directors": [{"Id": 11, "Name": "Coco"}, {"Id": "12", "Name": "Jambo"}]
}

The problem with the Post is that it doesn't work as expected when inserting a movie with one or more existing directors (that have already been added to the db). In such cases, those directors are readded to the db.

As a side note, EF implicitly adds the directors as new records in the Directors table when I add the movies dto with directors information, and also implicitly takes care of the junction table MoviesDirectors .

Here is my first attempt:

// POST: api/movies
public void Post([FromBody] MovieUpdateDto movie) 
{
    var bookToInsert = Mapper.Map<Movie>(movie);

    foreach (var director in movieToInsert.Directors)
    {
        var existingDirector = _unitOfWork.Directors.Find(d => d.Id == director.Id);
        if (existingDirector.Any())
        {
            // don't add director again to the database, but do add (directorId, bookId) in the MoviesDirectors junction table. 
            // How do I reference the junction table though? Should this work somehow without referencing the juntion table? 
        }
    }
    _unitOfWork.Movies.Add(movieToInsert);
    _unitOfWork.Complete();
}    

PS:

The junction table called MoviesDirectors is autogenerated by EF when setting the right configurations. More precisely, in the MovieConfiguration class, I have:

HasMany(c => c.Directors)
    .WithMany(t => t.Movies)
    .Map(m =>
    {
        m.ToTable("MoviesDirectors"); // a way to overwrite the name that EF gives this table
        m.MapLeftKey("MovieId");
        m.MapRightKey("DirectorId");
    });
    

which automatically creates MoviesDirectors .

For your second attempt you can do just foreach (var director in movieToInsert.Directors.ToList()) , but I would recommend just to check the director.Id to be not a default value ( 0 or Guid.Empty ) and if it is not - using Attach :

foreach (var director in movieToInsert.Directors)
{
    if (director.Id > 0)
    {
       _unitOfWork.Directors.Attach(director);
    }
}

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