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.