2016-08-04 14 views
0

ich zwei Klassen haben, wie folgt:Hinzufügen neuer Datensätze zu einem Entity Framework viel viele mit vorhandenen Aufzeichnungen

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

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

und Entity-Frameworks erstellt eine Tabelle in zwischen die Beziehung zwischen ihnen aufzunehmen.

Nun, meine Frage ist, wie kann ich einen neuen Rekord mit bestehenden Filmen und Rekorde hinzufügen? Es gibt zwei Teile auf diese Frage:

  1. Mit dem folgenden Verfahren, wie kann ich die Schauspieler zum Film hinzufügen, ohne alle bestehenden Beziehungen für den Film zu ersetzen:

    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(); 
    } 
    

Diese erstellt einen neuen Actor, der nicht das ist, was ich will.

  1. Mit dem folgende Verfahren, wie kann ich alle Akteure für einen Film mit der angegebenen Liste ersetzen:

    public void ReplaceRelationship(int movieId, int[] actorIds) 
    { 
    
    } 
    

einem Weg, mit dem zweiten Verfahren ist, alle vorhandenen zu löschen und sie zu lesen, aber ich versuche, die Menge von Db-Fahrten unten zu behalten.

Auch beim Hinzufügen möchte ich keine Duplikate hinzufügen, muss ich alle Beziehungen aus und vergleichen in meinem Code?

+0

Ich denke, man versucht, etwas und das hat nicht funktioniert. Könnten Sie fügen Details von dem, was Sie versucht haben, und warum das funktioniert nicht? Nicht sicher, was Sie meinen, indem Sie vorhandene Beziehungen ersetzen (das Hinzufügen ersetzt IMO nicht) – Default

+1

@Default Ich habe meinen Code hinzugefügt, um eine neue Beziehung hinzuzufügen, aber dies erstellt einen neuen Akteur, der nicht denselben wiederverwendet – ADringer

Antwort

0

1.

Wenn Sie das tun, sind Sie tatsächlich einen neuen Akteur zu schaffen.

movie.Actors.add(new Actor{ Id = actorId }); 

Was Sie tun sollten, ist zunächst das vorhandene anfügen und dann hinzufügen.

var actor = new Actor{ Id = actorId }; 
context.Actors.Attach(actor); 
movie.Actors.Add(actor); 

Oder in voller Beispiel:

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(); 
} 

Ein Weg, um mit der zweiten Methode ist es, alle vorhandenen zu löschen und sie readd, aber ich versuche, die Anzahl der Db-Trips niedrig zu halten.

Ja, ich verstehe dich total. Leider habe ich keine bessere Lösung gefunden, als tatsächlich Remove() auf jedem einzelnen zu nennen.

Auch beim Hinzufügen möchte ich keine Duplikate hinzufügen, muss ich alle Beziehungen aus und vergleichen in meinem Code?

Sie können überprüfen, ob das Element zuerst existiert. Aber in meinen Fällen hat EF das für mich geschafft.Meine Mapping-Tabelle hat zwei PK (eine für MovieId und eine für ActorId, die Duplikate nicht zulässt.

this.HasMany(t => t.Actors) 
     .WithMany(t => t.Movies) 
     .Map(m => 
     { 
      m.ToTable("ActorMovies"); 
      m.MapLeftKey("ActorId"); 
      m.MapRightKey("MovieId"); 
     });