无法使用.Attach()

时间:2016-12-16 20:35:49

标签: c# asp.net-mvc database entity-framework asp.net-core

我正在尝试更新我的UserRoles表,但它不会更新。我正在尝试更新两件事:1。电子邮件2.用户角色。因为更新需要在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 个答案:

答案 0 :(得分:2)

您修改此代码中的数据的方式,您不需要致电Attach上的AddContext来了解实体的更改,将自动发生。

从您从DbSet的{​​{1}}中提取实体的那一刻起,DbContext就会跟踪(附加)该实体。当您在DbContext上致电SaveChanges时,它会扫描其正在跟踪的任何实体,将当前值与旧值进行比较,以查找更改。然后将这些更改发送到数据库。

您应该能够从最初发布的内容中删除3行代码并使其正常工作。

DbContext

我注意到了一些其他的东西。看起来您可能正在为整个应用程序使用一个... 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) ... 实例。这通常被视为&#34; Anti-Patern&#34;在实体框架中。您应该为每个&#34;逻辑&#34;创建一个新的DbContext实例(DbContext}。你执行的操作。该实例应该仅在该操作的生命中存活。

在MVC中,这通常是每usingDbContext个实例。