我试图在ASP中从用户实体(ApplicationUser)设置EF 6.1中的多对多关系。. NET标识到自定义实体(组)。我使用代码优先和迁移与ASP的股票标准MVC样例应用程序。净的身份。运行Update-Database似乎工作得很好,因为我最终与所有的asp.net *表加上我的实体和一个链接表:
组
GroupAspNetUsers
我的ApplicationUser声明有一个Group的集合,同样我的Group也有一个ApplicationUser的集合:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<Group> Groups { get; set; }
我可以创建用户和组,但是无论如何我都不知道如何将它们链接起来。我希望这样的东西能起作用:
Group group = Context.Groups.Single(g => g.Id == 1);
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// link this user to a group
group.ApplicationUsers.Add(user);
Context.SaveChanges();
但是,当我运行上面的代码时,我得到一个DbEntityValidationException,说明用户名已经被占用。
我已经尝试加载2自定义实体并以这种方式链接它们,这将记录插入链接表中没有问题。
所以关于ApplicationUser是如何不同的,我不太明白。
我的自定义实体和ASP。Net Identity实体应该使用与从基本控制器继承的所有控制器相同的DB上下文。
更新:
我也试过从另一种方式来解决这个问题(向用户添加一个组),没有任何运气:
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// attempting to add group to a user
user.Groups.Add(group);
Context.SaveChanges();
这段代码运行时没有抛出错误,但是它没有向我的GroupAspNetUsers表添加记录。
下一步是尝试创建一个单独的实体(例如:UserInfo),它与ApplicationUser有1对1的映射。然后我应该能够设置从UserInfo到Group的多对多。
<<p> 解决方案/strong>双插入问题源于UserManager。CreateAsync调用,它将在不同的线程上创建用户。当前线程没有意识到这一点,然后尝试再次插入用户。
将方法更改为usermanager。Create解决了问题,但是正如@Horizon_Net指出的那样,混合身份和上下文方法还有其他问题(我遇到了)。
解决方案是创建用户,然后重定向到另一个控制器,将用户链接到一个组。
问题不是来自您的groups集合。下面两行是问题所在
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
...
Context.SaveChanges();
在幕后发生的事情是,第一个调用创建了一个用户。对于第二次调用,它再次尝试插入该用户。这就是为什么你得到这个错误消息的原因。
一般来说,您应该避免将Identity提供的方法与处理上下文本身的方法混合在一起。这可能会有很多副作用(就像你的例子一样)。参考一下这个线程