在使用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. 入手Arduino Yun,配合Blynk搞一波事情

    前言 原创文章,转载引用务必注明链接. 最近在闲鱼上与别人用RPi2尸体+好的BBB换了个Arduino Yun,等了几天赶在节前收到了.出奇的轻巧,产地台湾,官方正品做工就是精细~采用5v Micr ...

  2. 基于社交网络的情绪化分析IV

    基于社交网络的情绪化分析IV By 白熊花田(http://blog.csdn.net/whiterbear) 转载需注明出处,谢谢. 前面进行了微博数据的抓取,简单的处理,类似度分析.后面两篇进行学 ...

  3. POJ 3928 Ping pong 树状数组模板题

    開始用瓜神说的方法撸了一发线段树.早上没事闲的看了一下树状数组的方法,于是又写了一发树状数组 树状数组: #include <cstdio> #include <cstring> ...

  4. html5 式程序员表白

    html5 式程序员表白 王海庆 于 星期三, 04/06/2014 - 00:44 提交 今天是个好日子,2014年5月20日,表白的最佳时机,虽说孩子已经四岁.结婚已经五年.可是也不能够偷懒.于是 ...

  5. sql注入攻防 以php+mysql为例

    随着Web应用的高速发展和技术的不断成熟,对Web开发相关职位的需求量也越来越大,越来越多的人加入了Web开发的行列.但是由于程序员的水平参差不齐或是安全意识太低,很多程序员在编写代码时仅考虑了功能上 ...

  6. 【前端JS】radio 可单选可点击取消选中

    普通情况下 radio 单选框仅仅能实现多选一的效果,可是一旦选择当中一个后,这个单选框就不可点击取消其选中状态了.这样的功能在某些业务环境下并不适用.有时我们既须要单选框的多选一效果.也须要复选框的 ...

  7. 开源项目:单行日历(CalendarView)

    http://www.cnblogs.com/warnier-zhang/p/4750525.html CalendarView.zip

  8. 我为什么不喜欢 CoreData

    我为什么不喜欢 CoreData   我一直不喜欢 Core Data,以前不太敢明目张胆地这么表达,现在收集到越来越多相关的信息,所以给大家分享一下,我为什么不喜欢 Core Data. Core ...

  9. 赵雅智_SimpleCursorAdapter

    项目步骤 声明listView控件并获取显示的视图 获取显示的数据 设置显示的adapter 注冊点击事件 详细案例 实现效果: watermark/2/text/aHR0cDovL2Jsb2cuY3 ...

  10. VUE 之 路由 VueRouter

    1.VueRouter的安装 1.1.https://unpkg.com/vue-router/dist/vue-router.js下载安装. 1.2.<script src="./s ...