我有两个课程如下:
public class Movie
{
...
public virtual ICollection<Actor> Actors { get; set; }
}
public class Actor
{
...
public virtual ICollection<Movie> Movies { get; set; }
}
实体框架在其间创建一个表来记录它们之间的关系。
现在,我的问题是如何在现有电影和唱片中添加新唱片?这个问题分为两部分:
使用以下方法,如何在不替换影片的所有现有关系的情况下将actor添加到影片中:
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();
}
这会创建一个不是我想要的新Actor。
使用以下方法,如何用给定列表替换电影的所有演员:
public void ReplaceRelationship(int movieId, int[] actorIds)
{
}
使用第二种方法的方法是删除所有现有的并读取它们,但我试图保持Db的数量减少。
另外,在添加时我不想添加重复项,我是否必须将所有关系取出并在我的代码中进行比较?
答案 0 :(得分:0)
<强> 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");
});