更新:
我完全重写了我的答案,因为我对这个过程了解了很多,并意识到我的答案还远远不够完整。
首先,我创建了我的实体,继承自 IdentityXXX 类(此处仅提供一个作为示例):
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using NTier.Web.Core.Interfaces.Common;
using NTier.Web.Core.Interfaces.DataModels;
using NTier.Web.Core.Interfaces.Stores;
namespace NTier.Web.DataAccess.Entities
{
public sealed class MemberEntity : IdentityUser<Guid, MemberLogin, MemberRole, MemberClaim>,
IMemberDataModel, IAuditable
{
public MemberEntity()
{
Id = Guid.NewGuid();
}
#region Overrides of IdentityUser<Guid,MemberLogin,MemberRole,MemberClaim>
public override Guid Id
{
get { return base.Id; }
set
{
base.Id = value != Guid.Empty ? value : base.Id;
}
}
#region Overrides of IdentityUser<Guid,MemberLogin,MemberRole,MemberClaim>
public override string PasswordHash
{
get { return base.PasswordHash; }
set
{
base.PasswordHash = !string.IsNullOrWhiteSpace(value) ? value : base.PasswordHash ;
}
}
#endregion
#endregion
public Guid Identity
{
get { return Id; }
set
{
if (value != Guid.Empty)
{
Id = value;
}
}
}
public string Moniker { get; set; }
[MaxLength(256)]
public string FirstName { get; set; }
[MaxLength(256)]
public string LastName { get; set; }
[MaxLength(256)]
public string Middle { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<MemberEntity, Guid> 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;
}
#region Implementation of IAuditable
public DateTime DateTimeCreated { get; set; }
public DateTime? DateTimeModified { get; set; }
public DateTime? DateTimeDeleted { get; set; }
public DateTime? DateTimeArchived { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string DeletedBy { get; set; }
public string ArchivedBy { get; set; }
public bool IsDeleted { get; set; }
public bool IsArchived { get; set; }
#endregion
}
}
其次,我在我的 DbContext 中覆盖了 OnModelCreating 方法,如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null) throw new ArgumentNullException("modelBuilder");
modelBuilder.Entity<WebSiteEntity>()
.HasKey(site => site.Identity)
.ToTable("WebSite");
#region Security
modelBuilder.Entity<MemberEntity>()
.ToTable("Member")
.HasMany(u => u.Roles)
.WithRequired()
.HasForeignKey(ur => ur.UserId);
modelBuilder.Entity<MemberEntity>()
.HasMany(u => u.Claims)
.WithRequired()
.HasForeignKey(uc => uc.UserId);
modelBuilder.Entity<MemberEntity>()
.HasMany(u => u.Logins)
.WithRequired()
.HasForeignKey(ul => ul.UserId);
modelBuilder.Entity<MemberEntity>()
.Property(u => u.Moniker)
.HasMaxLength(50)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("UserNameIndex")
{
IsUnique = true,
IsClustered = false,
Order = 2
}))
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("MonikerIndex")
{
IsUnique = true,
IsClustered = false,
Order = 1
}));
modelBuilder.Entity<MemberEntity>()
.Property(u => u.LastName)
.HasMaxLength(256)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("UserNameIndex")
{
IsUnique = true,
IsClustered = false,
Order = 3
}))
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("MonikerIndex")
{
IsUnique = true,
IsClustered = false,
Order = 2
}));
;
modelBuilder.Entity<MemberEntity>()
.Property(u => u.FirstName)
.HasMaxLength(256)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("UserNameIndex")
{
IsUnique = true,
IsClustered = false,
Order = 4
}))
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("MonikerIndex")
{
IsUnique = true,
IsClustered = false,
Order = 3
}));
;
modelBuilder.Entity<MemberEntity>()
.Property(u => u.Middle)
.HasMaxLength(256);
modelBuilder.Entity<MemberEntity>()
.Property(u => u.UserName)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("UserNameIndex")
{
IsUnique = true,
IsClustered = false,
Order = 1
}))
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("MonikerIndex")
{
IsUnique = true,
IsClustered = false,
Order = 4
}));
modelBuilder.Entity<MemberEntity>()
.Property(u => u.Email)
.HasMaxLength(256);
modelBuilder.Entity<MemberRole>()
.HasKey(userRole => new
{
userRole.UserId,
userRole.RoleId
})
.ToTable("MemberRole");
modelBuilder.Entity<MemberLogin>()
.HasKey(login => new
{
login.UserId,
login.ProviderKey,
login.LoginProvider
})
.ToTable("MemberLogin");
modelBuilder.Entity<MemberClaim>()
.ToTable("MemberClaim");
modelBuilder.Entity<RoleEntity>()
.ToTable("Role");
modelBuilder.Entity<RoleEntity>()
.Property(r => r.Name)
.IsRequired()
.HasMaxLength(256)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("RoleNameIndex")
{
IsUnique = true
}));
modelBuilder.Entity<RoleEntity>()
.HasMany(r => r.Users)
.WithRequired()
.HasForeignKey(ur => ur.RoleId);
#endregion