2017-12-31 186 views
0

MVC5 웹 응용 프로그램을 빌드합니다. 나는 ID 프레임 워크를 사용했다. 나는 각 사용자가 그가 연관된 군대의 목록을 갖도록하려고 노력 중이다. 이들은 체크 박스를 통해 페이지에서 업데이트됩니다.MVC5 - ManytoMany ApplicationUser 사용 기존 행/열 대신에 새로운 행을 추가 함 오류

확장했습니다.이 추가 속성을 사용하여 기본 ApplicationUser 클래스를 확장했습니다.

public virtual ICollection<Army> Armies { get; set; } 

    public ApplicationUser() 
    { 
     Armies = new HashSet<Army>(); 
    } 

또한이 필드가 포함 된 군대 수업도 있습니다. 육군 테이블에는 약 10 개의 항목이 들어 있으며 각기 다른 군대를 자세하게 설명합니다.

public class Army 
{ 
    public int Id { get; set; } 
    public String Name { get; set; } 
    public String IconLocation { get; set; } 
    public virtual ICollection<ApplicationUser> Users { get; set; } 

    public Army() 
    { 
     Users = new HashSet<ApplicationUser>(); 
    } 
} 

그리고 내가 사용자는 사용자 관리 페이지에서 다음을 편집 할 수 DbContext

  protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder 
      .Entity<ApplicationUser>() 
      .HasMany(u => u.Armies) 
      .WithMany(t => t.Users) 
      .Map(m => 
      { 
       m.ToTable("UserArmies"); 
       m.MapLeftKey("UserId"); 
       m.MapRightKey("ArmyId"); 
      }); 

}

의 관계를 설정 한 다음이 체크 박스의 항목으로 표시됩니다.

public class CheckBoxItem 
{ 
    public int Id { get; set; } 
    public String Name { get; set; } 
    public bool IsChecked { get; set; } 
} 

제어기는 체크 박스 목록으로 군대 우회전 PopulateArmyCheckBoxList() 메소드를 호출한다. (이것은 원래 목록을 사용하여 완료되었지만 사전에 문제를 해결하려고 시도하는 동안 사전에 구현됩니다.) 프로그램의이 부분은 예상대로 작동하며 해당 확인란을 선택하여 올바르게 확인란을 표시합니다.

private List<CheckBoxItem> PopulateArmyCheckBoxList() 
    { 
     var userId = User.Identity.GetUserId(); 
     var userArmies = _context.Users.SingleOrDefault(u => u.Id == userId).Armies.ToDictionary(t=>t.Id, t=>t.Name); 

     var allArmies = _context.Armies.ToDictionary(t=>t.Id, t => t.Name); 
     var armyCheckBoxList = new List<CheckBoxItem>(); 


     foreach (var army in allArmies) 
     { 
      armyCheckBoxList.Add(new CheckBoxItem() 
      { 
       Id = army.Key, 
       Name = army.Value, 
       IsChecked = false 
      }); 
     } 

     foreach(var army in userArmies) 
     { 
      var cb = armyCheckBoxList.Find(c => c.Id == army.Key); 
      if(cb != null) 
       cb.IsChecked = true; 
     } 

     return armyCheckBoxList; 
    } 

는 뷰 모델은 사용자와 군대라는 CheckBoxItems의 목록이 포함되어 있습니다. 처음 액세스하는 경우, 사용자 == null이고 viewModel은 데이터로 채워집니다. 그렇지 않으면 데이터를 가져 와서 사용자를 업데이트합니다.

public async Task<ActionResult> Index(IndexViewModel viewModel) 
    { 
     var userId = User.Identity.GetUserId(); 

     if (viewModel.User == null) 
     { 
      var model = new IndexViewModel 
      { 
       User = UserManager.FindById(userId), 
       Armies = PopulateArmyCheckBoxList() 
      }; 
      return View(model); 
     } 

     var user = UserManager.FindById(userId); 
     user.UserName = viewModel.User.UserName; 
     user.Email = viewModel.User.Email; 
     user.ProfilePictureLocation = SaveProfileImage(user, viewModel.ProfilePicture); 
     UserManager.Update(user); 

     ViewBag.StatusMessage = "Your Profile Has Been Updated."; 
     viewModel.User = UserManager.FindById(User.Identity.GetUserId()); 
     return View(viewModel); 
    } 

최종 단계는 어디 까지나 끔찍한 잘못입니다. 데이터베이스의 UserArmies 테이블을 업데이트해야합니다. UserManager.Update (user)를 호출하기 전에 다음 코드 줄을 추가하여이 작업을 시도했습니다.

 user.Armies = GetUserArmies(user, viewModel.Armies); 

다음 메소드를 호출합니다. 먼저 이드의 목록을 얻어 selectedArmies라고 부릅니다. 그런 다음 데이터베이스에서 군대 목록을 가져 와서 모든 아군에 배치합니다. userArmies는 채우고 돌아갈 군대의 빈 목록입니다.

private List<Army> GetUserArmies(ApplicationUser user, List<CheckBoxItem> armies) 
    { 
     var selectedArmies = armies.Where(a => a.IsChecked).Select(a => a.Id).ToList(); 
     var allArmies = _context.Armies.ToList(); 

     var userArmies = new List<Army>(); 

     foreach (var army in selectedArmies) 
      userArmies.Add(allArmies.Find(t => t.Id == army)); 

     return userArmies; 
    } 

원하지 않는 결과가 2 개 있습니다. 첫 번째는 내가 현재 어떻게 지내는지입니다. 오류가 두 개체 사이의 관계는 그들이 다른 ObjectContext를 부착하고 있기 때문에 정의 개체를 할 수 없다는 발생

내가 군대 테이블이 어디 대신 다음과 같은 결과를 얻을 육군 클래스에서 가상 키워드를 제거하면 처음에는 새로운 이드의 군대 행을 복제했습니다. 그런 다음 새로운 UserArmy가 새로 생성 된 Exsiting Army의 복제본 아래에있는 데이터베이스에 저장됩니다. 그러면 내 체크 박스 목록이 두 배로 늘어납니다.

어디로 잘못 가고 있습니까? 어떤 도움을 주시면 감사하겠습니다.

추가 정보 또한 사용자 기사 클래스에는 동일한 군대 표가 사용됩니다. 이것은 매우 유사한 코드를 사용하고 중복을 만들지 않고 완벽하게 작동합니다.이것은 내가 UserManager와 _Context를 부르는 것과 관련이 있다는 것을 의미합니다.

답변

0

자신의 DbContext를 만들고 OnModelCreating 메서드를 재정의해야합니다.

public class MyDbContext : DbContext 
{ 
    public MyDbContext() : base("YourDefaultConnectionString") 
    {   
     // Database Initializer 
    } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     // Write your own model creation code; 
    } 
} 

희망이 있으면 도움이 될 것입니다.

+0

제공된 원본 코드에 표시된대로 이미 수행 했습니까? 이것이 Fluent API를 사용하여 내 관계를 개선 한 곳입니까? 나는 방법을 더 명확하게 무시하는 것을 보여주기 위해 나의 글을 바꿀 것이다. 내가 뭔가 추가했다면 당신은 더 힌트를 줄 수 있을까요? –

0

나는 데이터를 conbine 할 수 없습니다 어떤 이유로 답변

내가 데이터에 액세스 할 수 UserManager 및 _context (내 자신의 DbContext)를 사용하여 한을 발견했다 생각합니다. UserManager 대신 DBContext를 통해 사용자를 호출하기 위해 내 메서드를 바꿔서 오류가 발생하여 문제를 해결할 수있었습니다.