将新记录添加到实体框架中—许多都有现有记录
本文关键字:许多 记录 添加 新记录 实体 框架 | 更新日期: 2023-09-27 18:00:12
我有两个类,如下所示:
public class Movie
{
...
public virtual ICollection<Actor> Actors { get; set; }
}
public class Actor
{
...
public virtual ICollection<Movie> Movies { get; set; }
}
实体框架在它们之间创建一个表来记录它们之间的关系。
现在,我的问题是如何在现有电影和唱片中添加新唱片?这个问题有两个部分:
使用以下方法,如何在不替换电影的所有现有关系的情况下将演员添加到电影中:
public void AddRelationship(int movieId, int[] actorIds) { var movie = new Movie { Id = movieId }; context.Movies.Attach(movie); foreach(var actorId in actorIds) { movie.Actors.add(new Actor{ Id = actorId }); } context.SaveChanges(); }
这创造了一个新的演员,这不是我想要的。
使用以下方法,我如何用给定的列表替换电影的所有演员:
public void ReplaceRelationship(int movieId, int[] actorIds) { }
第二种方法的一种方法是删除所有现有的并读取它们,但我正在努力减少Db跳闸的数量。
此外,当添加时,我不想添加重复项,我是否必须在代码中找出所有关系并进行比较?
1.
当你这样做的时候,你实际上是在创造一个新的演员。
movie.Actors.add(new Actor{ Id = actorId });
你应该做的是首先附加现有的,然后添加它
var actor = new Actor{ Id = actorId };
context.Actors.Attach(actor);
movie.Actors.Add(actor);
或者完整的例子:
public void AddRelationship(int movieId, int[] actorIds)
{
var movie = _context.Movies.FirstOrDefault(x => x.Id == movieId);
// You might need to do include actors like this:
//_context.Movies.Include(x => x.Actors).FirstOrDefault(x => x.Id = movieId);
if(movie == null)
{
// Now what?
throw new Exception("Invalid movieId");
}
foreach(var actorId in actorIds)
{
var actor = new Actor
{
Id = actorId
};
_context.Actors.Attach(actor);
movie.Actors.Add(actor); // EF will detect if it already exists or not.
}
_context.SaveChanges();
}
2.
public void ReplaceRelationship(int movieId, int[] actorIds)
{
var movie = _context.Movies.FirstOrDefault(x => x.Id = movieId);
// You might need to do include actors like this:
//_context.Movies.Include(x => x.Actors).FirstOrDefault(x => x.Id = movieId);
if(movie == null)
{
// Now what?
throw new Exception("Invalid movieId");
}
// Get a list of the already existing actors, so we know which to remove.
var existingActorIds = movie.Actors.Select(x => x.Id).ToList();
// Add new actors.
foreach (var actorId in actorIds.Where(x => !existingActorIds .Contains(x.Id)))
{
var newActor = _context.Actors.Find(actorId );
// You might be able to use this instead.
// var newActor = new Actor { Id = actorId };
// _context.Actors.Attach(newActor);
movie.Actors.Add(newActor );
}
var idsToRemove =
existingActorIds.Where(x => !actorIds.Contains(x));
// Remove the old ones
foreach (var actorId in idsToRemove)
{
var actorEntity = movie.Actors.FirstOrDefault(x => x.Id== actorId );
// Again, you should be able to use Attach like above.
// I use FirstOrDefault() since I actually need the full entity later.
movie.Actors.Remove(actorEntity);
}
_context.SaveChanges();
}
第二种方法的一种方法是删除所有现有的读过了,但我正在努力减少Db的次数。
是的,我完全理解你。不幸的是,我没有找到比在每一个上实际调用Remove()
更好的解决方案。
此外,当添加时,我不想添加重复项,我必须获得所有的关系都在我的代码中进行比较?
您可以先检查项目是否存在。但在我的情况下,EF为我管理了这一点。我的映射表有两个PK(一个用于MovieId
,一个用于ActorId
,这不允许重复。
this.HasMany(t => t.Actors)
.WithMany(t => t.Movies)
.Map(m =>
{
m.ToTable("ActorMovies");
m.MapLeftKey("ActorId");
m.MapRightKey("MovieId");
});