如何在ASP.NET Core 6清洁架构中迁移Identity至Persistence项目
分步迁移Identity到MyProject.Persistence并隔离EF Core
1. 配置MyProject.Persistence依赖
给MyProject.Persistence安装以下NuGet包:
Microsoft.AspNetCore.Identity.EntityFrameworkCore(Identity与EF Core集成核心包)Microsoft.EntityFrameworkCore.SqlServer(根据你的数据库更换对应提供商,比如MySQL用Pomelo.EntityFrameworkCore.MySql)Microsoft.EntityFrameworkCore.Tools(用于EF Core迁移操作)
确保MyProject.Persistence已引用MyProject.Shared.Models(如果需要共享自定义Identity实体或DTO)
2. 迁移Identity相关文件
- 从MyProject.UI.Web的
Data文件夹,复制ApplicationDbContext.cs和Migrations目录到MyProject.Persistence下的Data子目录(没有就新建) - 修改复制后文件的命名空间:将
MyProject.UI.Web.Data替换为MyProject.Persistence.Data - 删除MyProject.UI.Web中的
Data文件夹
3. 调整ApplicationDbContext
在MyProject.Persistence的ApplicationDbContext.cs中,确保正确继承并配置:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace MyProject.Persistence.Data; public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // 如果有自定义Identity实体(如ApplicationUser),替换泛型参数: // public class ApplicationDbContext : IdentityDbContext<ApplicationUser> }
4. 封装Persistence层服务注册
在MyProject.Persistence中新建PersistenceServiceExtensions.cs,统一注册DbContext和Identity服务:
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using MyProject.Persistence.Data; namespace MyProject.Persistence; public static class PersistenceServiceExtensions { public static IServiceCollection AddPersistenceServices(this IServiceCollection services, string connectionString) { // 注册DbContext services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString)); // 注册Identity核心服务,绑定EF Core存储 services.AddIdentityCore<IdentityUser>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); // 若使用自定义User,替换IdentityUser为你的实体类 // services.AddIdentityCore<ApplicationUser>() return services; } }
5. 清理并配置MyProject.UI.Web
- 卸载MyProject.UI.Web中所有EF Core相关NuGet包(包括
Microsoft.EntityFrameworkCore.SqlServer、Microsoft.AspNetCore.Identity.EntityFrameworkCore等) - 在Program.cs中通过Persistence扩展方法注册服务,替换原有的Identity/EF Core配置:
using MyProject.Persistence; var builder = WebApplication.CreateBuilder(args); // 注册Persistence层服务,传入连接字符串 builder.Services.AddPersistenceServices(builder.Configuration.GetConnectionString("DefaultConnection")); // 添加MVC控制器和视图支持 builder.Services.AddControllersWithViews(); // 配置Identity认证方案 builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(); var app = builder.Build(); // 保留原有中间件配置(静态文件、路由、认证授权等) if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
6. 修复迁移命令执行
- Package Manager Console:设置默认项目为MyProject.Persistence,执行迁移时指定启动项目:
Add-Migration [迁移名称] -StartupProject MyProject.UI.Web Update-Database -StartupProject MyProject.UI.Web
- .NET CLI:
dotnet ef migrations add [迁移名称] --project MyProject.Persistence --startup-project MyProject.UI.Web dotnet ef database update --project MyProject.Persistence --startup-project MyProject.UI.Web
7. 适配登录业务流程
按照你的设计(UI→服务→API),需要通过业务服务层封装Identity逻辑,避免UI直接依赖Persistence:
- 新建MyProject.Services项目,引用MyProject.Persistence和MyProject.Shared.Models
- 在Services中实现认证服务:
using Microsoft.AspNetCore.Identity; namespace MyProject.Services; public class AuthService { private readonly UserManager<IdentityUser> _userManager; private readonly SignInManager<IdentityUser> _signInManager; public AuthService(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager) { _userManager = userManager; _signInManager = signInManager; } public async Task<SignInResult> LoginAsync(string email, string password, bool rememberMe) { var user = await _userManager.FindByEmailAsync(email); if (user == null) return SignInResult.Failed(); return await _signInManager.PasswordSignInAsync(user, password, rememberMe, lockoutOnFailure: false); } }
- 在Services中添加服务注册扩展:
using Microsoft.Extensions.DependencyInjection; namespace MyProject.Services; public static class ServiceExtensions { public static IServiceCollection AddBusinessServices(this IServiceCollection services) { services.AddScoped<AuthService>(); return services; } }
- 在UI.Web的Program.cs中注册业务服务:
builder.Services.AddBusinessServices();
- UI控制器注入
AuthService实现登录:
public class AccountController : Controller { private readonly AuthService _authService; public AccountController(AuthService authService) { _authService = authService; } [HttpPost] public async Task<IActionResult> Login(LoginViewModel model) { if (!ModelState.IsValid) return View(model); var result = await _authService.LoginAsync(model.Email, model.Password, model.RememberMe); if (result.Succeeded) return RedirectToAction("Index", "Home"); ModelState.AddModelError(string.Empty, "登录失败,请检查邮箱或密码"); return View(model); } }
关键注意事项
- 依赖链必须清晰:UI.Web → Services → Persistence → Shared.Models
- 迁移文件移动后,务必确认命名空间与项目结构匹配,避免编译错误
- 如需自定义Identity规则(如密码复杂度),可在Persistence的
AddPersistenceServices中通过AddIdentityCore链式配置(比如.AddPasswordValidator<CustomPasswordValidator>())
内容的提问来源于stack exchange,提问作者micex
相关产品推荐
相关产品推荐

