.NET Core洋葱架构中如何将Identity与数据层解耦?
解决方案:将ASP.NET Core Identity与数据层解耦
可行性说明
完全可行,ASP.NET Core支持将Identity的配置与业务数据库上下文分离,无需让业务DbContext继承IdentityDbContext,就能实现Identity与数据层的解耦,满足数据层不依赖Microsoft.AspNetCore相关包的需求。
具体实现步骤
1. 改造数据层的MyDbContext
按照你的需求,将数据层的MyDbContext改为直接继承DbContext,移除所有Identity相关的引用和代码,只保留业务实体的DbSet:
using Microsoft.EntityFrameworkCore; namespace DataLayer.Data { public class MyDbContext : DbContext { public DbSet<Table1> Table1 { get; set; } public DbSet<Table2> Table2 { get; set; } public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { } } }
2. 在Web层配置Identity与MyDbContext的关联
由于数据层无法引用Identity包,我们在Web层完成Identity的实体配置和服务注册:
步骤2.1:定义Identity实体(如ApplicationUser)
在Web层创建Identity用户实体,继承自IdentityUser(若需要自定义角色,也可创建IdentityRole子类):
using Microsoft.AspNetCore.Identity; namespace WebLayer.Models { public class ApplicationUser : IdentityUser<string> { // 可添加自定义用户属性 } }
步骤2.2:添加Identity模型配置扩展
在Web层创建扩展方法,用于向MyDbContext的模型中添加Identity所需的实体和表配置:
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using WebLayer.Models; public static class IdentityModelBuilderExtensions { public static void AddIdentityConfiguration(this ModelBuilder modelBuilder) { // 配置ApplicationUser实体 modelBuilder.Entity<ApplicationUser>(b => { b.HasKey(u => u.Id); b.HasIndex(u => u.NormalizedUserName).IsUnique(); b.HasIndex(u => u.NormalizedEmail).IsUnique(); b.Property(u => u.UserName).HasMaxLength(256); b.Property(u => u.NormalizedUserName).HasMaxLength(256); b.Property(u => u.Email).HasMaxLength(256); b.Property(u => u.NormalizedEmail).HasMaxLength(256); }); // 配置IdentityRole实体(若使用角色) modelBuilder.Entity<IdentityRole>(b => { b.HasKey(r => r.Id); b.HasIndex(r => r.NormalizedName).IsUnique(); b.Property(r => r.Name).HasMaxLength(256); b.Property(r => r.NormalizedName).HasMaxLength(256); }); // 配置用户-角色关联表 modelBuilder.Entity<IdentityUserRole<string>>(b => { b.HasKey(ur => new { ur.UserId, ur.RoleId }); b.HasOne(ur => ur.User).WithMany().HasForeignKey(ur => ur.UserId).IsRequired(); b.HasOne(ur => ur.Role).WithMany().HasForeignKey(ur => ur.RoleId).IsRequired(); }); // 按需添加其他Identity关联表配置 modelBuilder.Entity<IdentityUserClaim<string>>(b => b.HasKey(uc => uc.Id)); modelBuilder.Entity<IdentityUserLogin<string>>(b => b.HasKey(ul => new { ul.LoginProvider, ul.ProviderKey })); modelBuilder.Entity<IdentityUserToken<string>>(b => b.HasKey(ut => new { ut.UserId, ut.LoginProvider, ut.Name })); modelBuilder.Entity<IdentityRoleClaim<string>>(b => b.HasKey(rc => rc.Id)); } }
步骤2.3:注册MyDbContext并关联Identity配置
在Web层的Program.cs中,注册MyDbContext时调用上述扩展方法,将Identity的模型配置注入到MyDbContext中:
var builder = WebApplication.CreateBuilder(args); // 注册MyDbContext,添加Identity模型配置 builder.Services.AddDbContext<MyDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")) .UseModel(modelBuilder => { modelBuilder.AddIdentityConfiguration(); }));
步骤2.4:注册Identity服务
继续在Program.cs中注册Identity服务,指定使用MyDbContext作为存储:
// 注册Identity服务,使用MyDbContext作为存储 builder.Services.AddDefaultIdentity<ApplicationUser>(options => { options.SignIn.RequireConfirmedAccount = true; // 可添加其他Identity配置项 }) .AddEntityFrameworkStores<MyDbContext>();
3. 执行数据库迁移
由于Identity的模型配置在Web层,需要以Web层为启动项目执行EF Core迁移:
- 在Package Manager Console中,设置启动项目为Web层,默认项目为数据层(或包含迁移的项目)
- 执行迁移命令:
Add-Migration InitialCreateWithIdentity Update-Database
这样就能生成包含业务表和Identity表的数据库,同时数据层完全不依赖Microsoft.AspNetCore相关包,可在其他领域服务中直接复用MyDbContext。
内容的提问来源于stack exchange,提问作者DK_bhai
相关产品推荐
相关产品推荐

