2016-12-16 166 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实例。