从ApplicationUser添加多对多关系到自定义实体

时间:2014-07-01 11:46:55

标签: entity-framework-6 asp.net-identity

我尝试在ASP.NET 6.1中将用户实体(ApplicationUser)中的多对多关系设置为自定义实体(组)。我使用带有ASP.Net Identity的股票标准MVC示例应用程序使用Code First和Migrations。运行Update-Database似乎工作得很好,因为我最终得到了所有的AspNet *表以及我的实体和链接表:


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设置多对多。

双插入问题源于UserManager.CreateAsync调用,该调用将在不同的线程上创建用户。当前线程不知道这一点,然后尝试再次插入用户。

将方法更改为UserMannager.Create解决了这个问题,但是@Horizo​​n_Net指出混合身份和上下文方法存在其他问题(我遇到过)。

解决方案是创建用户,然后重定向到另一个控制器以将用户链接到一个组。这没有任何障碍。

1 个答案:

答案 0 :(得分:2)

问题不是来自您的群组。以下两行是问题

IdentityResult result = await UserManager.CreateAsync(user, model.Password);
...
Context.SaveChanges();

幕后发生的事情是,第一次调用会创建用户。通过第二次调用,它再次尝试插入此用户。这就是您收到此错误消息的原因。

通常,您应该避免混合使用Identity提供的方法并处理上下文本身。这可能会产生很多副作用(例如你的例子)。

供参考,请查看this thread