2017-06-01 4 views
1

asp.net mvcアプリケーションで初めてEFを使用しています。最後の2日間、私は同様の質問と例を読んでいますが、この時点までに私は何をしなければならないかを正確に理解していません。EF:子エンティティの追加、削除、または変更なしのエンティティの更新(多対多の関係)

多対多の関係を持つ2つのエンティティがあります。

モデル:

[Table("Unit")] 
public class UnitEntity 
{ 
    [Required] 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    [Required] 
    public UnitType Type { get; set; } 

    [StringLength(255)] 
    public string Title { get; set; } 

    ///some other properties 

    public virtual ICollection<UserEntity> Users { get; set; } 
} 

[Table("User")] 
public class UserEntity 
{ 
    [StringLength(255)] 
    public string Id { get; set; } 

    [Required] 
    public string UserName { get; set; } 

    [Required] 
    public string Email { get; set; } 


    public int Status { get; set; } 

    // some other properties 

    public virtual ICollection<UnitEntity> DepartmentUnits { get; set; } 
} 

そして、私のdbcontext中:

public virtual DbSet<UnitEntity> Units { get; set; } 
public virtual DbSet<UserEntity> Users { get; set; } 

modelBuilder.Entity<UserEntity>() 
      .HasMany(e => e.DepartmentUnits) 
      .WithMany(e => e.Users) 
      .Map(m => m.ToTable("UserDepartments").MapLeftKey("UserId").MapRightKey("DepartmentId")); 

各ユーザのDepartmentUnitsのリストが複数選択リストを使用してビューに更新され、コントローラに渡されます。

コントローラ方法:

[HttpPost] 
    public ActionResult UpdateUser(ExternalUserDTO userdata) 
    { 
     //list of UnitDepartments from the view 
     var userDepartments = new List<UnitEntity>(); 
     foreach (var unitid in userdata.DepartmentIds) 
     { 
      userDepartments.Add(manager.GetUnit(unitid)); 
     } 


     //create new user with data to update 
     UserEntity userentity = new UserEntity() 
     { 
      Id = userdata.Id, 
      DepartmentUnits = userDepartments, 
      Status = userdata.Status 

     }; 


     userManager.UpdateUser(userentity); 

     return new JsonResult { Data = new { Success = false } }; 
    } 

とのUserManagerクラス:私は私のUserDepartmentsテーブルを更新する必要が

public void UpdateUser(UserEntity entity) 
    { 
     var updentity = this.dataContext.Users.Find(entity.Id); 

     if (updentity == null) 
      throw new NullReferenceException("User not found"); 


     updentity.Status = entity.Status; 

     var newUnitIds = entity.DepartmentUnits.Select(u => u.Id); 
     var existingUnitIds = updentity.DepartmentUnits.Select(u => u.Id); 

     updentity.DepartmentUnits.Where(u => !newUnitIds.Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Remove(d)); 
     entity.DepartmentUnits.Where(u => newUnitIds.Except(existingUnitIds).Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Add(d)); 


     this.dataContext.Entry(updentity).State = EntityState.Modified; 


     foreach (var deptentity in updentity.DepartmentUnits) 
     { 
      if(newUnitIds.Contains(deptentity.Id)) 
      { 
       this.dataContext.Entry(deptentity).State = EntityState.Added; 
      } 
      if(existingUnitIds.Contains(deptentity.Id)) 
      { 
       this.dataContext.Entry(deptentity).State = EntityState.Unchanged; 
      } 
     } 


     try 
     { 
      this.dataContext.SaveChanges(); 

     } 
     catch (Exception) 
     { 
      throw new Exception("Update problem"); 
     } 

    } 

削除削除するために、(上記のモデルビルダーを参照)、新しい追加して保持特定のユーザーの既存のDepartmentUnit。上記は機能していない、私は失われており、私は何か助けに感謝します。

答えて

1

とすぐdataContext変数ライフタイムが単一UpdateUser操作のためにスコープされて、あなたは、問題のコレクションを含めて、データベースからをターゲットエンティティをロードすることによって、EF変更トラッカーはあなたのための作業のほとんどをやらせることができます、その後、単純に渡されたエンティティの対応するコレクションから作成されたスタブエンティティリストに置き換えます

public void UpdateUser(UserEntity entity) 
{ 
    // Load the exiting entity from the db, including the collection 
    var dbEntity = this.dataContext.Users 
     .Include(e => e.DepartmentUnits) 
     .FirstOrDefault(e => e.Id == entity.Id); 

    if (dbEntity == null) 
     throw new NullReferenceException("User not found"); 

    // Update the master information 
    this.dataContext.Entry(dbEntity).CurrentValues.SetValues(entity); 

    // Replace the collection with stubs created from the source collection 
    dbEntity.DepartmentUnits = entity.DepartmentUnits.Select(e => new UnitEntity { Id = e.Id }).ToList(); 

    // And that's all - EF change tracker will detect added/removed/unchanged links (and changed master properties) for you. 
    // Just commit the changes and you are done. 
    this.dataContext.SaveChanges(); 
} 

が、これはEF6で動作することに注意してください。 EFコアは現在、あなたが試みたものに類似したより多くの手作業を必要とします。

+0

FWIW、この行: 'this.dataContext.Entry(dbEntity).CurrentValues.SetValues(エンティティ);'異なるコンテキストにあるエンティティに関する例外をスローします。 ToList(); 'null値を持つUnitテーブルに新しい行を追加し、UserDepartmentsテーブルにエントリを追加します。この行は、' dbEntity.DepartmentUnits = entity.DepartmentUnits.Select(e => new UnitEntity {Id = e.Id} UnitIdは実際には存在しません。それにもかかわらず、私の問題を解決したのは、あなたが私を別の方法で考えさせたからです。ありがとう、私は私の下に私の仕事の解決策を入れます。 – tz2015

0

操作コード:

public void UpdateUser(UserEntity entity) 
    { 

     var updentity = this.dataContext.Users.Include(e => e.DepartmentUnits).FirstOrDefault(e => e.Id == entity.Id); 


     if (updentity == null) 
      throw new NullReferenceException("User not found"); 


     updentity.Status = entity.Status; 

     updentity.DepartmentUnits = entity.DepartmentUnits.Select(e => this.dataContext.Units.Find(e.Id)).ToList(); 


     try 
     { 
      this.dataContext.SaveChanges(); 

     } 
     catch (Exception) 
     { 
      throw new Exception("Update problem"); 
関連する問題