在使用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()));

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

  1. 关于Entity Framework更新的几种方式以及可能遇到的问题(附加类型“Model”的实体失败,因为相同类型的其他实体已具有相同的主键值)在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为

    在日常使用Entity Framework中,数据更新通常会用到.下面就简单封装了一个DBContext类 public partial class EFContext<T> : DbCo ...

  2. 附加类型的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值

    var list= DAL.LoadEntities(x => x.OrderCode == orderCode).AsNoTracking().ToList().FirstOrDefault( ...

  3. 因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 。。。

    因为相同类型的其他实体已具有相同的主键值.在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified&quo ...

  4. 错误:因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 解决方法

    在更新一个实体类的时候可能会有预先有一次查询或者其它操作,我们这样用目的是为了与提交的数据做一个比较之类的东西,如果先查询再对此类进行SaveChanges就会出错. 我们只要用AsNoTrackin ...

  5. 《Entity Framework 6 Recipes》中文翻译系列 (41) ------ 第七章 使用对象服务之标识关系中使用依赖实体与异步查询保存

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 7-7  标识关系中使用依赖实体 问题 你想在标识关系中插入,更新和删除一个依赖实体 ...

  6. 为什么分布式数据库中不使用uuid作为主键?

    分布式数据库当然也有主键的需求,但是为什么不直接使用uuid作为主键呢?作为曾经被这个问题困惑过的人,试着回答一下 1. UUID生成速率低下 Java的UUID依赖于SecureRandom.nex ...

  7. 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针

      您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...

  8. 解决:oracle+myBatis ResultMap 类型为 map 时返回结果中存在 timestamp 时使用 jackson 转 json 报错

    前言:最近在做一个通用查询单表的组件,所以 sql 的写法就是 select *,然后 resultType="map" ,然后使用 jackson @ResponseBody 返 ...

  9. 在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句:

    在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句: 如果是String类型的字符串进行判空的时候: <if test=&q ...

随机推荐

  1. Win10 - 默认图片查看器恢复

    1. 新建一个文本文件“1.txt” 2. 在“1.txt”中添加如下代码,并保存: Windows Registry Editor Version 5.00 ; Change Extension's ...

  2. Map与object的区别

    Map 对象保存键值对.任何值(对象或者原始值) 都可以作为一个键或一个值. 语法 new Map([iterable]) 参数 iterable Iterable 可以是一个数组或者其他 itera ...

  3. Mysql学习之十二:JDBC连接数据库之DriverManager方法

    JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包括7个步骤: 1.载入JDBC驱动程序: 在连接数据库之前.首先要载入想要连接的数据库的驱动到JVM(Java虚拟机). 这通过java.l ...

  4. Solidworks如何标注垂直度,平行度

    1 标注一个基准特征,放到一个平面的线上即可,比如下图生成了一个基准面A   2 点击形位公差,设置形位公差的符号,公差值,相对基准面(主要那一栏),然后不要点确定,直接在图上点击某个面,就生成一个形 ...

  5. linux字符设备驱动程序框架(老方法)

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #inclu ...

  6. SQLDMO注冊

    在维护人事系统时.师姐给我们提出一个功能上有问题. 备份数据库时.报黄页.然后须要我们寻找原因,作出解决方式. 一開始我从原先在本机上公布的系统入手,发现没有出现故障.可是.当对程序进行调试时,就出现 ...

  7. Firefox OS开发指南

    在海外社区Leanpub上线了<Firefox OS App开发>高速指南,指引开发人员尝试新技术. 这款<Firefox OS App开发>高速指南现已开放下载.HTML5开 ...

  8. 【C语言】统计数字在排序数组中出现的次数

    //数字在排序数组中出现的次数. //统计一个数字在排序数组中出现的次数.比如:排序数组{1,2,3,3,3,3,4,5}和数字3,因为3出现了4次,因此输出4. #include <stdio ...

  9. Java Unit Testing - JUnit & TestNG

    转自https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaUnitTesting.html yet another insignifican ...

  10. HDU 6143 Killer Names DP+快速密

    Killer Names Problem Description > Galen Marek, codenamed Starkiller, was a male Human apprentice ...