在使用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. BUPT复试专题—网络的核(2014)

    题目描述 给定一个无向网络G,共有N个节点(1到N),M条边,求网络的核. 网络的核:到网络中其他节点距离之和最小的节点,且对于不连通的两点,他们之间的距离为N,若有多组解,输出编号最小的节点 输入 ...

  2. Gas Station,转化为求最大序列的解法,和更简单简单的Jump解法。——贪心、转化

    Gas Station There are N gas stations along a circular route, where the amount of gas at station i is ...

  3. HDU 1398 Square Coins(母函数或dp)

    Square Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  4. thinkphp getField( )和field( )

    thinkphp getField( )和field( )   做数据库查询的时候,比较经常用到这两个,总是查手册,记不住,现在把它总结下,希望以后用的时候不查手册了. 不管是用select 查询数据 ...

  5. Entity Framework 6 Code First 实践系列(1):实体类配置-根据依赖配置关系和关联

    EF实体类的配置可以使用数据注释或Fluent API两种方式配置,Fluent API配置的关键在于搞清实体类的依赖关系,按此方法配置,快速高效合理.为了方便理解,我们使用简化的实体A和B以及A.B ...

  6. 如何查看Java进程并获取进程ID?

    1. 在 LINUX 命令平台输入 1-2 个字符后按 Tab 键会自动补全后面的部分(前提是要有这个东西,例如在装了 tomcat 的前提下, 输入 tomcat 的 to 按 tab).2. ps ...

  7. inheritance super overrides printMethod in Superclass override重写父方法

    Core Java Web Page http://horstmann.com/corejava.html [ inheritance ] package v1ch05.inheritance; im ...

  8. jquery.validate ajax验证

    $("#form1").validate({ rules: { ctl00$ContentPlaceHolder1$txtShopName: { remote: { type: & ...

  9. IE6span 高度问题

    IE6盒子的最小高度为20px,所以设置低于20px大小时,加上_overflow:hidden;

  10. MapReduce Join的使用

    一.Map端Join 可连接两个都非常大的数据集之间可使用map端连接,数据在到达map端之前就执行连接操作. 需满足: 两个要连接的数据集都先划分成相同数量的分区,相同的key要保证在同一分区中(每 ...