2014-01-21 24 views
5

我遇到了一个问题,即使用EF Codefirst正确保存多对多关系。我已经正确建模了我的类,并使用Fluent-API来正确建模连接表。我认为这个问题与使用断开连接的DTO有关。当我将更改保存到父实体(公寓)时,父实体上的筛选属性(如Title和UserId)可以正确保存,但对子实体(设施)的更改不会保存到多对多表中。实体框架与Codefirst,通用存储库,工作单元模式保存多对多关系

下面的代码流,这将有助于澄清事情:

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

我能得到的东西的工作通过创建一个condoRepository.UpdateCondo(公寓)方法如下:

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

然而,有没有更好的方法来做到这一点是通用的,并且不需要我每次需要保存多对多关系时创建自定义“更新”方法?这https://stackoverflow.com/a/11169307/3221076答案帮助澄清我认为问题是什么,但我不知道如何实施更通用的方法。

感谢, 杰森

回答

-1

我不知道如何完全通用,但我做了这样的事情,它允许您添加,删除和修改主从关系。 (我认为最初的想法来自Steven Sanderson,但我找不到它。)这段代码在我的DbContext中。希望能帮助到你。

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