C# EF Core向用户添加角色

C# EF Core向用户添加角色,c#,entity-framework-core,C#,Entity Framework Core,我想包括用户的角色列表 var users = Users .Include(u => u.UserRoles) .ToList() 我按照许多建议来解决问题,但没有一个对我有效: 所以可能有其他人也会处于同样的情况 Startup.cs services.AddIdentity<User, Role>() .AddEntityFrameworkStores<ApiDbCo

我想包括用户的角色列表

var users = Users
                .Include(u => u.UserRoles)
                .ToList()
我按照许多建议来解决问题,但没有一个对我有效:

所以可能有其他人也会处于同样的情况

Startup.cs

    services.AddIdentity<User, Role>()
        .AddEntityFrameworkStores<ApiDbContext>()
        .AddDefaultTokenProviders()
        ;//.AddUserStore<UserStore<User, Role, ApiDbContext, Guid>>()//, IdentityUserClaim<Guid>, UserRole, IdentityUserLogin<Guid>, IdentityUserToken<Guid>, IdentityRoleClaim<Guid>>>()
         //.AddRoleStore<RoleStore<Role, ApiDbContext, Guid>>();//, UserRole, IdentityRoleClaim < Guid >>> ();
services.AddIdentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
;//.AddUserStore()/,IdentityUserClaim,UserRole,IdentityUserLogin,IdentityUserToken,IdentityRoleClaim>>()
//.AddRoleStore();/,UserRole,IdentityRoleClaim>>();
[注意]:在评论中,有许多不同的尝试使迁移成功

Role.cs

 public class Role : IdentityRole<Guid>
 {
        public virtual ICollection<UserRole> UserRoles { get; } = new List<UserRole>();
 }
公共类角色:IdentityRole
{
公共虚拟ICollection用户角色{get;}=new List();
}
User.cs

public class User : IdentityUser<Guid>, IEntity
{
    public virtual ICollection<UserRole> UserRoles { get; } = new List<UserRole>();
}
public class User : IdentityUser<Guid>, IEntity
{
    public virtual ICollection<Role> Roles { get; } = new List<Role>();
}
public类用户:IdentityUser,IEntity
{
公共虚拟ICollection用户角色{get;}=new List();
}
UserRole.cs

public class UserRole : IdentityUserRole<Guid>
{
    public virtual User User { get; }
    public virtual Role Role { get; }
}
public类用户角色:IdentityUserRole
{
公共虚拟用户{get;}
公共虚拟角色{get;}
}
ApiDbContext.cs

public class ApiDbContext : IdentityDbContext<User, Role, Guid, IdentityUserClaim<Guid>, UserRole, IdentityUserLogin<Guid>, IdentityRoleClaim<Guid>, IdentityUserToken<Guid>>
{
        protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<User>()
            .HasMany(e => e.UserRoles)
            .WithOne()
            .HasForeignKey(e => e.UserId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);

        builder.Entity<UserRole>()
            .HasOne(e => e.User)
            .WithMany(e => e.UserRoles)
            .HasForeignKey(e => e.UserId);

        builder.Entity<UserRole>()
            .HasOne(e => e.Role)
            .WithMany(e => e.UserRoles)
            .HasForeignKey(e => e.RoleId);

        base.OnModelCreating(builder);
    }
公共类ApiDbContext:IdentityDbContext
{
模型创建时受保护的覆盖无效(ModelBuilder)
{
builder.Entity()
.HasMany(e=>e.UserRoles)
.WithOne()
.HasForeignKey(e=>e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity()
.HasOne(e=>e.User)
.WithMany(e=>e.UserRoles)
.HasForeignKey(e=>e.UserId);
builder.Entity()
.HasOne(e=>e.Role)
.WithMany(e=>e.UserRoles)
.HasForeignKey(e=>e.RoleId);
基于模型创建(生成器);
}
每次运行“添加迁移”时,无论下面的建议是什么,我总是:

        migrationBuilder.CreateTable(
            name: "AspNetUserRoles",
            columns: table => new
            {
                UserId = table.Column<Guid>(nullable: false),
                RoleId = table.Column<Guid>(nullable: false),
                RoleId1 = table.Column<Guid>(nullable: true),
                UserId1 = table.Column<Guid>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
                table.ForeignKey(
                    name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
                    column: x => x.RoleId,
                    principalTable: "AspNetRoles",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_AspNetUserRoles_AspNetRoles_RoleId1",
                    column: x => x.RoleId1,
                    principalTable: "AspNetRoles",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_AspNetUserRoles_AspNetUsers_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_AspNetUserRoles_AspNetUsers_UserId1",
                    column: x => x.UserId1,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });
migrationBuilder.CreateTable(
名称:“AspNetUserRoles”,
列:表=>new
{
UserId=table.Column(可空:false),
RoleId=表.列(可空:false),
RoleId1=表.列(可空:true),
UserId1=table.Column(可空:true)
},
约束:表=>
{
表.PrimaryKey(“PK_AspNetUserRoles”,x=>new{x.UserId,x.RoleId});
表1.外键(
名称:“FK_AspNetUserRoles_AspNetRoles_RoleId”,
列:x=>x.RoleId,
原则性:“AspNetRoles”,
主栏:“Id”,
onDelete:引用。级联);
表1.外键(
名称:“FK_AspNetUserRoles_AspNetRoles_RoleId1”,
列:x=>x.RoleId1,
原则性:“AspNetRoles”,
主栏:“Id”,
onDelete:referentialiction.Restrict);
表1.外键(
名称:“FK_AspNetUserRoles_AspNetUsers_UserId”,
列:x=>x.UserId,
原则性:“AspNetUsers”,
主栏:“Id”,
onDelete:引用。级联);
表1.外键(
名称:“FK_AspNetUserRoles_AspNetUsers_UserId1”,
列:x=>x.UserId1,
原则性:“AspNetUsers”,
主栏:“Id”,
onDelete:referentialiction.Restrict);
});
角色1和用户1不应该在那里

我正在使用:

<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.2" />


是否有人知道如何解决此问题?

这不是EF core特有的,但希望能帮助您:

在我看来,您似乎过度定义了多对多关系。除非您在UserRoles表上需要其他属性,否则您不需要直接引用它。我会将您的ApidContext简化为:

public class ApiDbContext : IdentityDbContext<User, Role, Guid, IdentityUserClaim<Guid>, UserRole, IdentityUserLogin<Guid>, IdentityRoleClaim<Guid>, IdentityUserToken<Guid>>
{
        protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<User>()
            .HasMany(e => e.Role)
            .WithMany(r => r.User)
            .OnDelete(DeleteBehavior.Cascade);

        base.OnModelCreating(builder);
    }
}
公共类ApiDbContext:IdentityDbContext
{
模型创建时受保护的覆盖无效(ModelBuilder)
{
builder.Entity()
.HasMany(e=>e.Role)
.WithMany(r=>r.User)
.OnDelete(DeleteBehavior.Cascade);
基于模型创建(生成器);
}
}

进一步来看,我认为您必须如下更新user和role,因为您不想像我提到的那样显式定义UserRoles表: Role.cs

公共类角色:IdentityRole
{
公共虚拟ICollection用户{get;}=new List();
}
User.cs

public class User : IdentityUser<Guid>, IEntity
{
    public virtual ICollection<UserRole> UserRoles { get; } = new List<UserRole>();
}
public class User : IdentityUser<Guid>, IEntity
{
    public virtual ICollection<Role> Roles { get; } = new List<Role>();
}
public类用户:IdentityUser,IEntity
{
公共虚拟ICollection角色{get;}=new List();
}
您可能还需要更新我以前的代码,以将名称固定为复数:

public class ApiDbContext : IdentityDbContext<User, Role, Guid, IdentityUserClaim<Guid>, UserRole, IdentityUserLogin<Guid>, IdentityRoleClaim<Guid>, IdentityUserToken<Guid>>
{
        protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<User>()
            .HasMany(e => e.Roles)
            .WithMany(r => r.Users)
            .OnDelete(DeleteBehavior.Cascade);

        base.OnModelCreating(builder);
    }
}
公共类ApiDbContext:IdentityDbContext
{
模型创建时受保护的覆盖无效(ModelBuilder)
{
builder.Entity()
.HasMany(e=>e.Roles)
.WithMany(r=>r.Users)
.OnDelete(DeleteBehavior.Cascade);
基于模型创建(生成器);
}
}

尝试向UserRole的属性添加setter

public class UserRole : IdentityUserRole<Guid>
{
    public virtual User User { get; set; }
    public virtual Role Role { get; set; }
}
public类用户角色:IdentityUserRole
{
公共虚拟用户用户{get;set;}
公共虚拟角色{get;set;}
}
如果您需要它是只读的,您可以添加一个私有构造函数

public class UserRole : IdentityUserRole<Guid>
{
    private User _user;
    private Role _role;

    private UserRole()
    {
    }

    public UserRole(User user, Role role)
    {
        _user = user;
        _role = role;
    }

    public virtual User User => _user;
    public virtual Role Role => _role;
}
public类用户角色:IdentityUserRole
{
私人用户(u User),;
私人角色;
私有用户角色()
{
}
公共用户角色(用户用户,角色)
{
_用户=用户;
_角色=角色;
}
公共虚拟用户用户=>\u用户;
公共虚拟角色角色=>\u角色;
}
但是,您需要在dbcontext中配置私有字段

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserRole>().Property(u => u.User).HasField("_user");
    modelBuilder.Entity<UserRole>().Property(u => u.Role).HasField("_role");
}
模型创建时受保护的覆盖无效(ModelBuilder modelBuild