zoukankan      html  css  js  c++  java
  • 附加类型“UniversalReviewSystem.Models.ApplicationUser”的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值

    在使用asp.net Identity2 的 UserManager RoleManager 时,同时还有其他仓储类型接口,能实现用户扩展信息的修改,用户注册没有问题。当修改用户信息时,出现了如下异常。

     
    控制器代码:

    public class AccountController : Controller
    {
    private IDepartmentService _departmentService;

    public AccountController(IDepartmentService departmentService)
    {
    _departmentService = departmentService;

    }

    private ApplicationUserManager _userManager;

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, ApplicationRoleManager roleManager, IDepartmentService departmentService)
    {
    UserManager = userManager;
    SignInManager = signInManager;
    RoleManager = roleManager;
    _departmentService = departmentService;
    }

    public ApplicationUserManager UserManager
    {
    get
    {
    //return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();

    return _userManager ?? new ApplicationUserManager(new UserStore<ApplicationUser>(ContextFactory.GetCurrentContext()));
    }
    private set
    {
    _userManager = value;
    }
    }

    private ApplicationRoleManager _roleManager;
    public ApplicationRoleManager RoleManager
    {
    get
    {
    //return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
    return _roleManager ?? new ApplicationRoleManager(new RoleStore<ApplicationRole>(ContextFactory.GetCurrentContext()));
    }
    set
    {
    _roleManager = value;
    }
    }

    ///创建用户不会产生异常。

    // GET: /Account/Create
    //[Authorize(Roles="SuperAdmin")]
    public async Task<ActionResult> Create() //由原Register 方法修改成Create方法
    {
    ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "RoleRealName");
    ViewBag.DepartmentID = new SelectList(await _departmentService.FindAll().ToListAsync(), "DepartmentID", "DepartmentName");
    // RegisterViewModel registerViewModel = new RegisterViewModel(); //此处可以初始化一个实例,为视图返回一个一些默认值的对象。
    return View();
    }

    //
    // POST: /Account/Create
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Create(RegisterViewModel model, params string[] selectedRoles)//可变数组参数。 模型绑定自动完成,给selectedRoles 可变参数数组传入参数。
    {
    if (ModelState.IsValid)
    {
    var user = new ApplicationUser { UserName = model.UserName, Email = model.Email,RealName=model.RealName, Gender=model.Gender,Birthday=model.Birthday,ProfessionalTitle=model.ProfessionalTitle,InCollege=model.InCollege,DepartmentID=model.DepartmentID};
    var userResult = await UserManager.CreateAsync(user, model.Password);//添加用户//在数据库中创建了这个用户,那么就生成了UserID 了。

    //给用户添加角色
    if (userResult.Succeeded)
    {
    // await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

    // 有关如何启用帐户确认和密码重置的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=320771
    // 发送包含此链接的电子邮件
    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
    // await UserManager.SendEmailAsync(user.Id, "确认你的帐户", "请通过单击 <a href="" + callbackUrl + "">這裏</a>来确认你的帐户");

    if (selectedRoles != null)
    {
    var result = await UserManager.AddToRolesAsync(user.Id, selectedRoles);
    if (!result.Succeeded)
    {
    ModelState.AddModelError("", result.Errors.First());
    ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "RoleRealName");
    ViewBag.DepartmentID = new SelectList(await _departmentService.FindAll().ToListAsync(), "DepartmentID", "DepartmentName");
    return View(model);

    }
    }

    }

    else
    {
    ModelState.AddModelError("",userResult.Errors.First());
    ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "RoleRealName");
    ViewBag.DepartmentID = new SelectList(await _departmentService.FindAll().ToListAsync(), "DepartmentID", "DepartmentName");
    return View(model);
    }

    return RedirectToAction("Index"); //如果用户添加成功,角色创建成功就返回Index.2、如果用户添加成功,但没有选中角色,也返回Index.


    }
    // 如果我们进行到这一步时某个地方出错,则重新显示表单

    ViewBag.RoleID = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "RoleRealName");
    ViewBag.DepartmentID = new SelectList(await _departmentService.FindAll().ToListAsync(), "DepartmentID", "DepartmentName");

    return View(model);
    }

    //Get Account/EditUser 系统管理员修改其他人的信息
    public async Task<ActionResult> EditUser(string Id)
    {
    if (string.IsNullOrEmpty(Id))
    {
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest); //HttpStatusCode.BadRequest 在System.Net 命名空间下面。
    }

    var _user = await UserManager.FindByIdAsync(Id);
    if (_user == null)
    {
    return HttpNotFound();
    }

    var userRoles = await UserManager.GetRolesAsync(_user.Id);

    var editUser = new EditUserViewModel
    {
    Id = _user.Id,
    UserName = _user.UserName,
    Email = _user.Email,
    RealName = _user.RealName,
    Gender = _user.Gender,
    Birthday = _user.Birthday,
    InCollege = _user.InCollege,
    ProfessionalTitle = _user.ProfessionalTitle,
    RolesList = RoleManager.Roles.ToList().Select(x => new SelectListItem() //建立一个投影,如果角色中包含当前用户的角色,就选中此角色。
    {
    Text =x.RoleRealName + "-"+ x.Description,
    Value =x.Name,
    Selected =userRoles.Contains(x.Name)
    })

    };

    ViewBag.DepartmentList = new SelectList(_departmentService.FindAll().OrderBy(d => d.DepartmentName), "DepartmentID", "DepartmentName",_user.DepartmentID);

    return View(editUser);

    }
    /// <summary>
    /// 管理员编辑其他用户的信息
    /// </summary>
    /// <param name="user"></param>
    /// <param name="selectedRoles"></param>
    /// <returns></returns>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> EditUser([Bind(Include = "Id,UserName,Email,RealName,Gender,Birthday,DepartmentID,InCollege,ProfessionalTitle")] EditUserViewModel user, params string[] selectedRoles)
    {

    if (ModelState.IsValid)
    {
    //var _user = await UserManager.Users.AsNoTracking().SingleOrDefaultAsync(x => x.Id == user.Id);
    var _user = await UserManager.FindByIdAsync(user.Id);
    if (_user == null)
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

    _user.UserName = user.UserName;
    _user.Email = user.Email;
    _user.RealName = user.RealName;
    _user.Gender = user.Gender;
    _user.Birthday =user.Birthday;
    _user.DepartmentID = user.DepartmentID;
    _user.InCollege = user.InCollege;
    _user.ProfessionalTitle = user.ProfessionalTitle;


    var userRoles = await UserManager.GetRolesAsync(_user.Id);
    selectedRoles = selectedRoles ?? new string[] { };

    var result = await UserManager.AddToRolesAsync(user.Id, selectedRoles.Except(userRoles).ToArray<string>());
    if (!result.Succeeded)
    {
    ModelState.AddModelError("", result.Errors.First());
    ViewBag.DepartmentList = new SelectList(_departmentService.FindAll().OrderBy(d => d.DepartmentName), "DepartmentID", "DepartmentName", _user.DepartmentID);
    return View(user);
    }

    result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRoles).ToArray<string>());
    if (!result.Succeeded)
    {
    ModelState.AddModelError("", result.Errors.First());
    ViewBag.DepartmentList = new SelectList(_departmentService.FindAll().OrderBy(d => d.DepartmentName), "DepartmentID", "DepartmentName", _user.DepartmentID);
    return View(user);
    }

    await UserManager.UpdateAsync(_user); //异步更新用户信息  执行到此处出现 了   “附加类型“UniversalReviewSystem.Models.ApplicationUser”的实体失败,因为相同类型的其他实体已具有相同的主键值。”的异常。

    return RedirectToAction("Index");
    }

    ModelState.AddModelError("", "绑定失败");
    ViewBag.DepartmentList = new SelectList(_departmentService.FindAll().OrderBy(d => d.DepartmentName), "DepartmentID", "DepartmentName", user.DepartmentID);
    return View(user);

    }

    另外,还定义一个静态的工厂类,用于产生数据库上下文。

    public static class ContextFactory //静态类不能被实例化,只能有静态成员。
    {
    public static UniversalReviewSystemDbContext GetCurrentContext()
    {
    UniversalReviewSystemDbContext context = CallContext.GetData("UniversalReviewSystemContext") as UniversalReviewSystemDbContext;
    if (context == null)
    {
    context = new UniversalReviewSystemDbContext();
    CallContext.SetData("UniversalReviewSystemContext", context);
    }

    return context;

    }

    }

    出现异常的原因,可能是UserManager、RoleManager使用了不同的数据库上下文。 ContextFactory 使用CallContext 并不能保证数据库上下文一致。 把数据库上下文更改一下就行了。但同时增加了 userManager 用户的验证逻辑。

    在UserManager 和RoleManager 的属性中,

    恢复默认的 

    get
    {
    return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();

    }

    get
    {
    return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();

    }

    也可以在控制器中 为UserManager,RoleManager 使用同一数据库上下文对象。

    UniversalReviewSystemDbContext db =ContextFactory.GetCurrentContext();

     return _userManager ?? new ApplicationUserManager(new UserStore<ApplicationUser>(db));

     return  _roleManager ??  new ApplicationRoleManager(new RoleStore<ApplicationRole>(ContextFactory.GetCurrentContext()));

  • 相关阅读:
    日志处理
    md5加密
    os 模块
    time模块
    函数的进阶
    参数 返回值
    文件操作
    集合 拷贝
    linux如何更快的远程拷贝?scp,tar,rsync?
    修改内核临时端口范围
  • 原文地址:https://www.cnblogs.com/liuyuanhao/p/5072525.html
Copyright © 2011-2022 走看看