![](/img/trans.png)
[英]Unit testing Entity Framework 6 with IdentityDbContext
[英]Entity Framework Core 3.1 merge IdentityDbContext with myDbContext
我想將默認標識DbContext
與其他表(我自己的DbContext
)合並; 我對標識DbContext
逆向工程:它提供模型類(某些模型是部分模型)和一個DbContext
:
namespace pakshavad.Data
{
public partial class aspnetpakshavadContext : DbContext
{
public aspnetpakshavadContext()
{
}
public aspnetpakshavadContext(DbContextOptions<aspnetpakshavadContext> options)
: base(options)
{
}
public virtual DbSet<AspNetRoleClaims> AspNetRoleClaims { get; set; }
public virtual DbSet<AspNetRoles> AspNetRoles { get; set; }
public virtual DbSet<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual DbSet<AspNetUserLogins> AspNetUserLogins { get; set; }
public virtual DbSet<AspNetUserRoles> AspNetUserRoles { get; set; }
public virtual DbSet<AspNetUserTokens> AspNetUserTokens { get; set; }
public virtual DbSet<AspNetUsers> AspNetUsers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer("Server=.\\MSSQLSERVER2017;Database=aspnet-pakshavad;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AspNetRoleClaims>(entity =>
{
entity.HasIndex(e => e.RoleId);
entity.Property(e => e.RoleId).IsRequired();
entity.HasOne(d => d.Role)
.WithMany(p => p.AspNetRoleClaims)
.HasForeignKey(d => d.RoleId);
});
modelBuilder.Entity<AspNetRoles>(entity =>
{
entity.HasIndex(e => e.NormalizedName)
.HasName("RoleNameIndex")
.IsUnique()
.HasFilter("([NormalizedName] IS NOT NULL)");
entity.Property(e => e.Name).HasMaxLength(256);
entity.Property(e => e.NormalizedName).HasMaxLength(256);
});
modelBuilder.Entity<AspNetUserClaims>(entity =>
{
entity.HasIndex(e => e.UserId);
entity.Property(e => e.UserId).IsRequired();
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserClaims)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserLogins>(entity =>
{
entity.HasKey(e => new { e.LoginProvider, e.ProviderKey });
entity.HasIndex(e => e.UserId);
entity.Property(e => e.LoginProvider).HasMaxLength(128);
entity.Property(e => e.ProviderKey).HasMaxLength(128);
entity.Property(e => e.UserId).IsRequired();
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserLogins)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserRoles>(entity =>
{
entity.HasKey(e => new { e.UserId, e.RoleId });
entity.HasIndex(e => e.RoleId);
entity.HasOne(d => d.Role)
.WithMany(p => p.AspNetUserRoles)
.HasForeignKey(d => d.RoleId);
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserRoles)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUserTokens>(entity =>
{
entity.HasKey(e => new { e.UserId, e.LoginProvider, e.Name });
entity.Property(e => e.LoginProvider).HasMaxLength(128);
entity.Property(e => e.Name).HasMaxLength(128);
entity.HasOne(d => d.User)
.WithMany(p => p.AspNetUserTokens)
.HasForeignKey(d => d.UserId);
});
modelBuilder.Entity<AspNetUsers>(entity =>
{
entity.HasIndex(e => e.NormalizedEmail)
.HasName("EmailIndex");
entity.HasIndex(e => e.NormalizedUserName)
.HasName("UserNameIndex")
.IsUnique()
.HasFilter("([NormalizedUserName] IS NOT NULL)");
entity.Property(e => e.Email).HasMaxLength(256);
entity.Property(e => e.NormalizedEmail).HasMaxLength(256);
entity.Property(e => e.NormalizedUserName).HasMaxLength(256);
entity.Property(e => e.UserName).HasMaxLength(256);
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
我將這些類復制到我的項目中。 例如 :
namespace Domain.Models.Identity
{
public partial class AspNetUser : BaseEntity
{
public AspNetUser()
{
AspNetUserClaims = new HashSet<AspNetUserClaim>();
AspNetUserLogins = new HashSet<AspNetUserLogin>();
AspNetUserRoles = new HashSet<AspNetUserRole>();
AspNetUserTokens = new HashSet<AspNetUserToken>();
}
public string UserName { get; set; }
public string NormalizedUserName { get; set; }
public string Email { get; set; }
public string NormalizedEmail { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string ConcurrencyStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual ICollection<AspNetUserRole> AspNetUserRoles { get; set; }
public virtual ICollection<AspNetUserToken> AspNetUserTokens { get; set; }
}
public partial class AspNetUserConfigure : IEntityTypeConfiguration<AspNetUser>
{
public void Configure(EntityTypeBuilder<AspNetUser> builder)
{
builder.HasIndex(e => e.NormalizedEmail)
.HasName("EmailIndex");
builder.HasIndex(e => e.NormalizedUserName)
.HasName("UserNameIndex")
.IsUnique()
.HasFilter("([NormalizedUserName] IS NOT NULL)");
builder.Property(e => e.Email).HasMaxLength(256);
builder.Property(e => e.NormalizedEmail).HasMaxLength(256);
builder.Property(e => e.NormalizedUserName).HasMaxLength(256);
builder.Property(e => e.UserName).HasMaxLength(256);
}
}
}
在MyDbContext
(在另一個類庫中),在我的項目中,我使用反射和IEntityTypeConfiguration
接口來自動創建 DbSets :
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entitiesAssembly = typeof(IEntity).Assembly;
modelBuilder.RegisterAllEntities<IEntity>(entitiesAssembly);
modelBuilder.RegisterEntityTypeConfiguration(entitiesAssembly);
modelBuilder.AddRestrictDeleteBehaviorConvention();
modelBuilder.AddSequentialGuidForIdConvention();
modelBuilder.AddPluralizingTableNameConvention();
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
但對於
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
方法,我得到一個錯誤:
分部方法必須在分部類、分部結構或分部接口中聲明
我不知道如何解決這個錯誤。 有人可以幫助我嗎?
第二個問題:我的DbContext
是否需要從IdentityDbContext
類繼承?
既然你是問你是否應該繼承你的類IdentityDbContext
所有,我的回答將是一大肯定的請。 通過這樣做,您將不必反編譯庫代碼並自己支持它。 Microsoft 和社區為您維護它做得足夠好 - 節省您的時間。 因此,這也有望解決您的第一個問題。
據我所知,您已經從標准庫中復制了所有DbSet
屬性和大多數AspNetUserConfigure
。 對於這個答案,我假設您想覆蓋某些行為並將該.HasFilter("([NormalizedUserName] IS NOT NULL)")
到您的AspNetUser
。
public class aspnetpakshavadContext: IdentityDbContext {
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("your-connection-string"); // you will notice I removed .IsConfigured check - I believe this is redundant as OnConfiguring should always have it set to `false`
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(builder); // this is calling all relevant code from IdentityDbContext that you have previously copied. Yours will go afterwards to ensure your changes are applied last
modelBuilder.ApplyConfiguration(new MyAspNetUserConfiguration());// your extension point to modify particular entity model
}
public class MyAspNetUserConfiguration: IEntityTypeConfiguration<PortalUser>
{
public void Configure(EntityTypeBuilder<AspNetUser> builder)
{
builder.HasFilter("([NormalizedUserName] IS NOT NULL)"); // Builders are chained, so as long as you've called this after base method `OnModelCreating` above - this should add to existing model.
}
}
}
希望這就是你所追求的。
附帶說明一下,我不確定您的部分實現來自哪里,因為IdentityDbContext
的原始代碼似乎沒有任何...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.