2016-08-04 72 views
0

我有兩個類,如下所示:添加新記錄到實體框架多對多的現有記錄

public class Movie 
{ 
    ... 
    public virtual ICollection<Actor> Actors { get; set; } 
} 

public class Actor 
{ 
    ... 
    public virtual ICollection<Movie> Movies { get; set; } 
} 

與實體框架建立在與以記錄它們之間的關係的表。

現在,我的問題是如何添加一個新的記錄與現有的電影和記錄?有兩個部分對這個問題:

  1. 用下面的方法,我怎樣才能的演員增加了影片,而無需更換現有的所有關係的電影:

    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旅行的數量。

    此外,當添加我不想添加重複項,我必須得到所有的關係,並在我的代碼比較?

    +0

    我想你試過的東西,沒有工作,你可以添加你嘗試過什麼,爲什麼細節這不起作用嗎?不知道你的意思是通過替換現有的關係(添加不替代IMO) – Default

    +1

    @Default我已經添加了我的代碼來添加一個新的關係,但是這會創建一個新的actor,而不是重複使用同一個 – ADringer

    回答

    0

    當你這樣做,你實際上是創建一個新的演員。

    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"); 
         }); 
    
    相關問題