2014-01-21 11 views
5

Ich habe ein Problem damit, viele-zu-viele-Beziehungen korrekt mit EF Codefirst zu speichern. Ich habe meine Klassen korrekt modelliert und die Fluent-API verwendet, um die Join-Tabelle korrekt zu modellieren. Ich denke, das Problem hat damit zu tun, mit einem DTO ohne Verbindung zu arbeiten. Wenn ich Änderungen an der übergeordneten Entität (Condo) speichere, werden Skalareigenschaften für die übergeordnete Entität (wie Titel und UserId) korrekt gespeichert, aber Änderungen an einer untergeordneten Entität (Amenities) werden nicht in der Tabelle "Viele bis viele" gespeichert.Entitätsframework Viele-zu-viele-Beziehung mit Codefirst, generisches Repository, Arbeitseinheitsmuster

Hier ist der Code Fluss, die Dinge klären helfen:

public ICommandResult Execute(CreateOrUpdateCondoCommand command) 
    { 
     ICollection<Amenity> amenities = new List<Amenity>(); 

     foreach (var item in command.Amenities) 
     { 
      Amenity amenity = new Amenity { AmenityId = item.AmenityId }; 
      amenities.Add(amenity); 
     } 

     var condo = new Condo 
     { 
      [...other properties] 
      Title = command.Title,    
      Amenities = amenities    
     };     

     if (condo.CondoId == 0) 
     { 
      condoRepository.Add(condo); 
     } 
     else 
     { 
      condoRepository.Update(condo); 
     } 

     unitOfWork.Commit(); 

     return new CommandResult(true); 
    } 

    /// <summary> 
    /// Updates the entity. 
    /// </summary> 
    /// <param name="entity">The entity</param> 
    public virtual void Update(T entity) 
    { 
     dbset.Attach(entity); 
     dataContext.Entry(entity).State = EntityState.Modified; 
    } 

ich in der Lage war, die Dinge zum Laufen zu bringen, indem ein condoRepository.UpdateCondo (Wohnung) Verfahren wie folgt zu erstellen:

/// <summary> 
    /// Method for updating a condo 
    /// </summary> 
    /// <param name="condo">The condo to update</param> 
    public void UpdateCondo(Condo condo) 
    { 
     var updatedCondo = this.DataContext.Set<Condo>().Include("Amenities") 
      .Single(x => x.CondoId == condo.CondoId); 

     // Set the attributes 
     [other properties here...] 
     updatedCondo.Title = condo.Title;   

     updatedCondo.Amenities.Clear(); 

     foreach (var amenity in condo.Amenities) 
     { 
      var amenityToAttach = this.DataContext.Amenities.Single(x => x.AmenityId == amenity.AmenityId); 
      updatedCondo.Amenities.Add(amenityToAttach);     
     } 

     this.Update(updatedCondo); 
    } 

jedoch Gibt es einen besseren generischen Weg dies zu tun und erfordert nicht, dass ich jedes Mal eine benutzerdefinierte "Update" -Methode erstelle, wenn ich eine Viele-zu-Viele-Beziehung speichern muss? Diese https://stackoverflow.com/a/11169307/3221076 Antwort half zu klären, was ich denke, das Problem ist, aber ich bin mir nicht sicher, wie man einen allgemeineren Ansatz implementiert.

Danke, Jason

Antwort

-1

Ich weiß nicht, es komplett generisch zu machen, aber ich habe so etwas getan, das erlaubt, Master-Detail-Beziehungen hinzuzufügen, zu entfernen und zu modifizieren. (Ich denke, dass die ursprüngliche Idee von Steven Sanderson kam, aber ich konnte es nicht finden.) Dieser Code ist in meinem DbContext. Ich hoffe es hilft.

public Condo UpdateSheet(Condo condo) { 
    Guard.IsNotNull(condo); 

    List<long> retainedAmenityIds = (from amenity in condo.Amenities 
             where amenity.Id != 0 
             select amenity.Id).ToList(); 
    List<Amenity> retainedAmenities = (from amenity in condo.Amenities 
             where amenity.Id != 0 
             select amenity).ToList(); 
    string sql = String.Format("SELECT Id FROM {0} WHERE CondoId = {1}", GetTableName<Amenity>(), condo.Id); 
    List<long> deletedAmenityIds = Database.SqlQuery<long>(sql).Except(retainedAmenityIds).ToList(); 
    if (0 < deletedAmenityIds.Count) { 
     foreach (var id in deletedAmenityIds) { 
      Amenity amenity = Amenities.Single(a => a.Id == id); 
      Amenities.Remove(amenity); 
     } 
    } 
    List<Amenity> addedAmenities = condo.Amenities.Except(retainedAmenities).ToList(); 
    foreach (var amenity in addedAmenities) { 
     amenity.SheetId = condo.Id; 
     Entry(amenity).State = EntityState.Added; 
    } 
    foreach (var amenity in retainedAmenities) { Entry(amenity).State = EntityState.Modified; } 
    Entry(condo).State = EntityState.Modified; 
    SaveChanges(); 
    return condo; 
} 
Verwandte Themen