2016-12-16 129 views
1

我試圖更新我的UserRoles表,但它不會更新。我試圖更新兩件事:1.電子郵件2.用戶角色。因爲更新需要在兩個表中進行,所以我使用了兩個單獨的命令。當我單獨運行電子郵件更新(用戶)時,它的工作原理,但如果我更新角色(AspUserRoles),它什麼都不做。當我運行它時,它都不起作用,因爲UserRoles.Attach(userRole)阻止它更新。我也沒有錯誤。無法更新。安裝()

我檢查了ApplicationRole.Id和ApplicationUser.Id是否有值,它確實返回了我想要的值。

enter image description here

這裏是我的UserController.cs:

public async Task<IActionResult> Edit(UserViewModel model, Guid id) 
{ 
    var alert = new Alert(); 

    try 
    { 
     if(!ModelState.IsValid) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.INVALID; 
      throw new Exception(); 
     }  


     var originalModel = ApplicationDbContext.Users.FirstOrDefault(u => u.Id == id);  
     var userRole = ApplicationDbContext.UserRoles.FirstOrDefault(i => i.UserId == id); 


     if(originalModel == null) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.NOTEXISTS; 
      throw new Exception(); 

     } 


     originalModel.Email = model.ApplicationUser.Email; 

     userRole.RoleId = model.ApplicationRole.Id; 


     ApplicationDbContext.Users.Attach(originalModel); 
     ApplicationDbContext.UserRoles.Attach(userRole); 


     ApplicationDbContext.Entry(originalModel).State = EntityState.Modified; 


     if (await ApplicationDbContext.SaveChangesAsync() == 0) 
     { 
      alert.Message = alert.ExceptionMessage = ApplicationDbContextMessage.EDITNOK; 
      throw new Exception(); 
     } 

     alert.Message = ApplicationDbContextMessage.EDITOK; 
     return RedirectToAction("Index"); 
    } 
    catch(Exception ex) 
    { 
     alert.Type = AlertType.Error; 
     alert.ExceptionMessage = ex.Message; 

     model = await ViewModel(model.ApplicationUser); 

     ModelState.AddModelError(string.Empty, alert.ExceptionMessage); 
    } 
    return View(model); 
} 
+1

您不應該在這些對象上調用'Attach',它們來自它們保存的相同上下文,並且它們永遠不會斷開連接。你是否嘗試過這種方式,而不調用'Attach'或者搞亂'EntityState'? –

+0

我做了,它不起作用。當我做Add(userRole)而不是Attach(userRole)時,它確實在UserRole表中添加了一個新行,但是我有一個具有相同UserId的dublicate ... – hxwtch

+0

你不需要調用'Add'。只需更改屬性,並在上下文中調用「SaveChanges」。你應該能夠拿到你原來的發佈代碼,刪除2個表示'Attach'的行,以及改變'State'的行,並讓它工作。 –

回答

2

你在這個代碼修改數據的方式,你不需要調用AttachAddContext讓它知道實體的變化,這將自動發生。

從您從DbContextDbSet中拉出實體的那一刻開始,它正在被該DbContext跟蹤(附加)。當您在DbContext上調用SaveChanges時,它將掃描它正在跟蹤的任何實體,將當前值與舊值進行比較,以查找更改。這些更改會發送到數據庫。

你應該從字面上刪除你最初發布的3行代碼並使其工作。

... 
originalModel.Email = model.ApplicationUser.Email; 
userRole.RoleId = model.ApplicationRole.Id; 

ApplicationDbContext.Users.Attach(originalModel); // <--- Delete this line 
ApplicationDbContext.UserRoles.Attach(userRole); // <--- Delete this line 
ApplicationDbContext.Entry(originalModel).State = EntityState.Modified; // <--- Delete this line 

if (await ApplicationDbContext.SaveChangesAsync() == 0) 
... 

一點別的東西,我注意到了。看起來你可能會爲整個應用程序使用一個單一的DbContext實例。這通常被認爲是實體框架中的「反模式」。您應爲每個執行的「邏輯」操作創建一個新的DbContext實例(使用using)。該實例應該只在該操作的整個生命週期內有效。

在MVC中,這通常是每ActionMethod一個DbContext實例。