我正在尝试映射用户之间的一对多关系&小组。我希望用户对他们加入的每个组都有一个单独的排名,只相对于该组。不幸的是,EF无法绘制我想要的地图,我已经被困了两天,试图找出原因。
IdentityModels.cs:
namespace MapGroupsToRoles.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public ApplicationUser() { this.RolesToGroups = new HashSet<GroupToRoles>(); }
public virtual ICollection<GroupToRoles> RolesToGroups { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class GroupToRoles
{
public virtual int GroupToRolesId { get; set; }
public GroupToRoles() { }
public virtual ApplicationUser User { get; set; }
public virtual Group Group { get; set; }
public virtual ClanRole Role { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public System.Data.Entity.DbSet<GroupToRoles> GroupToRolesTable { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Entity<ApplicationUser>().ToTable("Users");
// modelbuilder.Entity<ApplicationUser>().Ignore(u => u.Id);
modelbuilder.Entity<ApplicationUser>().HasKey(u => u.Id);
modelbuilder.Entity<ApplicationUser>().HasMany(u => u.RolesToGroups).WithRequired().WillCascadeOnDelete(true);
modelbuilder.Entity<GroupToRoles>().ToTable("GroupToRolesTable").HasKey(u => u.GroupToRolesId);
modelbuilder.Entity<IdentityUserLogin>().HasKey(u => u.ProviderKey);
modelbuilder.Entity<IdentityUserRole>().HasKey(u => u.RoleId);
modelbuilder.Entity<Group>().ToTable("Groups");
modelbuilder.Entity<Group>().HasKey(u => u.GroupId);
modelbuilder.Entity<Group>().HasMany(u => u.Roles).WithRequired().WillCascadeOnDelete(true);
}
}
}
上面:这里需要注意的重要部分是:
public class GroupToRoles
{
public virtual int GroupToRolesId { get; set; }
public GroupToRoles() { }
public virtual ApplicationUser User { get; set; }
public virtual Group Group { get; set; }
public virtual ClanRole Role { get; set; }
}
和
public virtual ICollection<GroupToRoles> RolesToGroups { get; set; }
在ApplicationUser类中。
分组.cs:
namespace MapGroupsToRoles.Models
{
public class Group
{
public int GroupId { get; set; }
public Group() { this.Roles = new HashSet<GroupToRoles>(); }
public virtual string GroupName { get; set; }
public virtual ICollection<GroupToRoles> Roles { get; set; }
}
}
对,那么我得到了什么结果?1.两个哈希集(即Group.cs和ApplicationUser中的GroupToRoles集(都没有出现。。。2.分组表显示group_GroupId1和group_GroupId。。。1从哪里来?!
任何帮助都将不胜感激!!!!
编辑_____________
因此,我想重新迭代,将用户映射到组,每个组有一个角色,并且是多个组的成员。因此,它是用户和"GroupToRoles"类之间的一对多映射(反过来又映射一对多组(。
示例:约翰是a、b、c组的成员对于a组,他是管理员,b组他是成员c组他是的访客
我不认为我可以使用(如果我错了,请纠正我(标准的ASP角色(这就是我创建"ClanRole"类的原因,因为我还希望每个用户都有一个全局角色,可以处理整个网站的管理权限(而不仅仅是用户创建的组(。
基本上,我希望能够将ApplicationUser类映射到许多"GroupToRoles"。从那时起,其他一切都应该到位。然而,它很抗拒,我不知道为什么!
非常感谢
回答这个问题所需的步骤远远超出预期。我们将在接下来的几周内编写一份指南,并在此处提供链接。
简要概述:
-
创建一个单独的上下文:添加到web.config&添加以下内容:
public class MyContext : DbContext { public MyContext () : base("DefaultConnection") { } public static MyContext Create() { return new MyContext (); } }
-
删除ApplicationDbContext,构建以快速找到引用它的位置,并用新的上下文替换它们
-
将fluent改为(放在上下文中(:
public System.Data.Entity.DbSet<GroupToRoles> GroupToRolesTable { get; set; } public System.Data.Entity.DbSet<Group> Groups { get; set; } public System.Data.Entity.DbSet<ApplicationUser> Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelbuilder) { modelbuilder.Entity<ApplicationUser>().ToTable("Users"); modelbuilder.Entity<ApplicationUser>().HasKey(u => u.Id); modelbuilder.Entity<ApplicationUser>().HasMany(u => u.RolesToGroups);//.WithRequired(/*u => u.User*/).HasForeignKey(u => u.UserId); modelbuilder.Entity<GroupToRoles>().ToTable("GroupToRolesTable").HasKey(u => u.GroupToRolesId); modelbuilder.Entity<IdentityUserLogin>().HasKey(u => u.ProviderKey); modelbuilder.Entity<IdentityUserRole>().HasKey(u => u.RoleId); modelbuilder.Entity<Group>().ToTable("Groups"); modelbuilder.Entity<Group>().HasKey(u => u.GroupId); modelbuilder.Entity<Group>().HasMany(u => u.Roles);//.WithRequired(/*u => u.Group*/).HasForeignKey(u => u.GroupId); }
我真的对你的想法感到困惑。
为什么一个用户可以分配多个组?(与角色没有区别(。这个概念产生了大量冗余数据。
我认为一个用户应该只能分配一个组,0-1到Many。
例如:应用程序有3个组:admin、user、anonym。
- 管理员拥有所有角色
- 用户具有角色"home、usermanager等">
- 匿名者具有角色"home">
你必须像这样改变实体的结构:
身份用户
public class IdentityUser<TKey, TLogin, TClaim, TGroup, TGroupRole> : IUser<TKey>
where TLogin : IdentityUserLogin<TKey>
where TClaim : IdentityUserClaim<TKey>
where TGroup : IdentityGroup<TKey, TGroupRole>
where TGroupRole : IdentityGroupRole<TKey>
{
public virtual string Email { get; set; }
public virtual bool EmailConfirmed { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string PhoneNumber { get; set; }
public virtual bool PhoneNumberConfirmed { get; set; }
public virtual bool TwoFactorEnabled { get; set; }
public virtual DateTime? LockoutEndDateUtc { get; set; }
public virtual bool LockoutEnabled { get; set; }
public virtual int AccessFailedCount { get; set; }
public virtual ICollection<TClaim> Claims { get; private set; }
public virtual ICollection<TLogin> Logins { get; private set; }
public virtual TGroup Group { get; set; }
public virtual TKey Id { get; set; }
public virtual string UserName { get; set; }
public IdentityUser()
{
this.Claims = new List<TClaim>();
this.Logins = new List<TLogin>();
}
}
身份组
public class IdentityGroup<TKey, TGroupRole> : IGroup<TKey>
where TGroupRole : IdentityGroupRole<TKey>
{
public IdentityGroup()
{
Roles = new List<TGroupRole>();
}
public TKey Id { get; set; }
public string Name { get; set; }
public virtual ICollection<TGroupRole> Roles { get; private set; }
}
GroupRole
public class IdentityGroupRole<TKey>
{
public virtual TKey RoleId { get; set; }
public virtual TKey GroupId { get; set; }
}
IdentityDbContext
public class IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserClaim, TGroup, TGroupRole> : DbContext
where TUser : IdentityUser<TKey, TUserLogin, TUserClaim, TGroup, TGroupRole>
where TRole : IdentityRole<TKey, TGroupRole>
where TUserLogin : IdentityUserLogin<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TGroup : IdentityGroup<TKey, TGroupRole>
where TGroupRole : IdentityGroupRole<TKey>
{
private IdentityConfiguration _config;
public virtual IDbSet<TUser> Users { get; set; }
public virtual IDbSet<TRole> Roles { get; set; }
public virtual IDbSet<TGroup> Groups { get; set; }
public bool RequireUniqueEmail { get; set; }
public IdentityDbContext()
: this("DefaultConnection", new IdentityConfiguration())
{
}
public IdentityDbContext(string nameOrConnectionString)
: this(nameOrConnectionString, new IdentityConfiguration())
{
}
public IdentityDbContext(string nameOrConnectionString, IdentityConfiguration config)
: base(nameOrConnectionString)
{
_config = config;
}
public IdentityDbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
var user = modelBuilder.Entity<TUser>().ToTable(_config.UserTableName, _config.Schema);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.HasOptional(u => u.Group).WithMany().Map(m => m.MapKey("GroupId"));
user.Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true }));
// CONSIDER: u.Email is Required if set on options?
user.Property(u => u.Email).HasMaxLength(256);
modelBuilder.Entity<TGroupRole>().HasKey((TGroupRole r) => new
{
r.GroupId,
r.RoleId
}).ToTable(_config.GroupRoleTableName, _config.Schema);
modelBuilder.Entity<TUserLogin>().HasKey((TUserLogin l) => new
{
l.LoginProvider,
l.ProviderKey,
l.UserId
}).ToTable(_config.LoginTableName, _config.Schema);
modelBuilder.Entity<TUserClaim>().ToTable(_config.ClaimTableName, _config.Schema);
var role = modelBuilder.Entity<TRole>()
.ToTable(_config.RoleTableName, _config.Schema);
role.Property(r => r.Name)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("RoleNameIndex") { IsUnique = true }));
role.HasMany(r => r.Groups).WithRequired().HasForeignKey(ur => ur.RoleId).WillCascadeOnDelete();
var group = modelBuilder.Entity<TGroup>()
.ToTable(_config.GroupTableName, _config.Schema);
group.Property(r => r.Name)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("GroupNameIndex") { IsUnique = true }));
group.HasMany(r => r.Roles).WithRequired().HasForeignKey(ur => ur.GroupId).WillCascadeOnDelete();
//group.HasMany(g => g.Users).WithOptional().Map(m => m.MapKey("GroupId"));
}
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
if (entityEntry != null && entityEntry.State == EntityState.Added)
{
List<DbValidationError> list = new List<DbValidationError>();
TUser user = entityEntry.Entity as TUser;
if (user != null)
{
if (this.Users.Any((TUser u) => string.Equals(u.UserName, user.UserName)))
{
list.Add(new DbValidationError("User", string.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateUserName, new object[]
{
user.UserName
})));
}
if (this.RequireUniqueEmail && this.Users.Any((TUser u) => string.Equals(u.Email, user.Email)))
{
list.Add(new DbValidationError("User", string.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateEmail, new object[]
{
user.Email
})));
}
}
else
{
TRole role = entityEntry.Entity as TRole;
if (role != null && this.Roles.Any((TRole r) => string.Equals(r.Name, role.Name)))
{
list.Add(new DbValidationError("Role", string.Format(CultureInfo.CurrentCulture, IdentityResources.RoleAlreadyExists, new object[]
{
role.Name
})));
}
}
if (list.Any<DbValidationError>())
{
return new DbEntityValidationResult(entityEntry, list);
}
}
return base.ValidateEntity(entityEntry, items);
}
}
我刚刚完成我的图书馆,完整的来源你可以在这里下载
或者你可以通过nuget在这里添加库