我正在开发一个应用程序,用于记录注册访问网页上某些资源的用户。我使用带有ASP.NET身份的ASP.NET MVC 5。我对Email和UserName使用相同的值。我有一个存储网页的表。我还在AspNetUsers表中添加了一个WebpageId列来标识网页。实际上,在AspNetUsers表和网页表之间有很多关系,但出于某种原因,我想在AspNetUsers表中为用户创建多条记录 - 每个用户注册的网页都有一条记录。
如果具有user@examplemail.com的用户注册到网页1,则并不意味着他已注册到网页2。当他使用相同的电子邮件注册到网页2时,对他来说实际上完全不可见,他已经作为网页1的用户在系统中注册。
为了在AspNetUsers表中拥有多个具有相同UserName的记录,我删除了UserName上的唯一索引,而是我在两列上创建了一个唯一索引:UserName和WebpageId。
但是当我尝试使用已经注册到网页1的电子邮件地址注册到网页2时,我得到 DbEntityValidationException ,并带有以下验证消息:“用户名用户@ examplemail.com 已被采纳“。当UserManger用于创建新用户时,会在AccountControler.Register()方法中抛出此内容。
我第一次尝试解决问题的方法是自定义UserManager 类。我创建了一个UserManager的子类,我以一种他们寻找一对电子邮件+网页或名称+网页的方式覆盖 FindByEmailAsync 和 FindByNameAsync 方法:
var existingUser = this.db.Users
.FirstOrDefault(x => x.UserName == userName &&
x.WebpageId == webpageId);
return existingUser;
我的第二次尝试是另外自定义此UserManager的UserValidator 。我在那里做了类似于上面的代码 - 尝试让用户具有相同的UserName和webpageId。找不到用户时,我返回IdentityResult.Success。
没有成功。仍然出现DbEntityValidationException并显示“Username user@examplemail.com已经采取”验证错误。
知道哪个ASP.NET Identity组件仍然在寻找具有用户名的用户(不检查webpageId)?我应该如何自定义ASP.NET身份来处理这种情况?
以下是异常callstack的一部分:
at System.Data.Entity.Internal.InternalContext.SaveChangesAsync(CancellationToken cancellationToken) 在System.Data.Entity.Internal.LazyInternalContext.SaveChangesAsync(CancellationToken cancellationToken) 在System.Data.Entity.DbContext.SaveChangesAsync(CancellationToken cancellationToken) 在System.Data.Entity.DbContext.SaveChangesAsync() 在Microsoft.AspNet.Identity.EntityFramework.UserStore
6.<SaveChanges>d__31.MoveNext() (...) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at UserRegistrationSystem.Web.Controllers.AccountController.d__11.MoveNext()in i:\ Repo \ RegistrationSystem \ UserRegistrationSystem.Web \ Controllers \ AccountController.cs:第126行
仅供参考,我也在ASP.NET Identity forum上提出了同样的问题。
答案 0 :(得分:0)
您所描述的内容听起来像多租户。
我已经回答了相关问题here,并提供了一个库来实现它
https://github.com/JSkimming/AspNet.Identity.EntityFramework.Multitenant