从ApplicationUser到自定义实体添加多对多关系 [英] Adding Many to Many relationship from ApplicationUser to custom entity

查看:138
本文介绍了从ApplicationUser到自定义实体添加多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在EF 6.1中从ASP.NET身份中的用户实体(ApplicationUser)到自定义实体(组)设置多对多关系。我正在使用带有ASP.Net Identity的股票标准MVC示例应用程序的Code First和Migrations。运行更新 - 数据库似乎很好地工作,因为我结束了所有的AspNet *表加上我的实体和一个链接表:



br>
GroupAspNetUsers



我的ApplicationUser声明有一个Group的集合,同样我的Group还有一个ApplicationUser的集合: p>

  public class ApplicationUser:IdentityUser 
{
public virtual ICollection< Group>组{get;组; }

我可以创建用户和组,但对于我来说,我无法解决如何链接他们我会期待这样的工作:

 组组= 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)
{
//将此用户链接到组
group.ApplicationUsers.Add(user);
Context.SaveChanges();

但是,当我运行上面的代码时,我得到一个DbEntityValidationException,表示用户名已经被使用了。



我已经尝试加载2个自定义实体并以这种方式链接它们,将链接表中的记录插入没有问题。



所以有一些我不关心ApplicationUser的不同之处。



我的自定义实体和ASP.Net Identity实体应该使用与所有控制器从基本控制器继承的相同的DB上下文。



更新:

我也尝试从其他方式接近这个(向用户添加一个组),没有任何运气:

  IdentityResult result = await UserManager.CreateAsync(user,model.Password); 
if(result.Succeeded)
{
//尝试向用户添加组
user.Groups.Add(group);
Context.SaveChanges();

此代码运行时不会发生错误,但是不会将记录添加到GroupAspNetUsers表中



我的下一步是尝试创建一个与ApplicationUser进行1到1映射的单独实体(例如UserInfo)。那么我应该可以设置从UserInfo到Group的一对多。



解决方案



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



将方法更改为UserMannager.Create解决了问题,但是@Horizo​​n_Net指出混合身份和上下文方法(遇到的问题)还有其他问题。 / p>

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

解决方案

问题不是来自你的团体集合。以下两行是问题

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

幕后发生的是用第一次调用创建用户。第二次调用再次尝试插入此用户。这就是为什么你收到这个错误消息的原因。



一般来说,你应该避免混合Identity给你的方法和上下文本身。这可能会产生很多副作用(例如在您的示例中)。



有关参考,请参阅这个线程


I'm trying to setup a many to many relationship in EF 6.1 from the User entity (ApplicationUser) in ASP.NET Identity to a custom entity (Group). I'm using Code First and Migrations with the stock standard MVC sample app with ASP.Net Identity. Running Update-Database seems to work nicely as I end up with all the AspNet* tables plus my entity and a linking table:

Groups
GroupAspNetUsers

My ApplicationUser declaration has a collection of Group, and likewise my Group has a collection of ApplicationUser:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<Group> Groups { get; set; }

I can create users and groups, but for the life of me I can't work out how to link them. I would have expected something like this to work:

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();

However when I run the code above, I get a DbEntityValidationException stating the user name is already taken.

I've tried loading 2 custom entities and linking them in this way, which inserts a record into the linking table no problem.

So there is something I don't follow about how ApplicationUser is different.

My custom entities and the ASP.Net Identity entities should be using the same DB context as all my controllers inherit from a base controller.

UPDATE:
I've also tried approaching this from the other way around (add a group to a user), without any luck:

IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
    // attempting to add group to a user
    user.Groups.Add(group);
    Context.SaveChanges();    

This code runs without throwing an error, however it doesn't add a record to my GroupAspNetUsers table though.

My next step is to try creating a separate entity (eg. UserInfo) which has a 1 to 1 mapping with ApplicationUser. Then I should be able to setup a many to many from UserInfo to Group.

SOLUTION

The double insert problem stems from the UserManager.CreateAsync call, which will create the user on a different thread. The current thread, being unaware of this, then tries to insert the user again.

Changing the method to UserMannager.Create solved the problem, however as @Horizon_Net pointed out there are other issues with mixing identity and context methods (which I ran into).

The solution was to create the user, then redirect off to another controller to link the user to a group. This worked without a hitch.

解决方案

The problem does not come from your groups collection. The following two lines are the problem

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

What happens behind the scenes is that with the first call a user is created. With the second call it again tries to insert this user. That's the reason why you get this error message.

In general, you should avoid to mix the methods Identity gives you and working on the context itself. This can have a lot of side effects (like in your example).

For reference have a look at this thread

这篇关于从ApplicationUser到自定义实体添加多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆