.NET Core7项目集成Identity:现有EF Core上下文冲突解决问询
我有一个基于.NET Core 7、使用EF Core的应用,里面已经有多个经过测试的可用实体。现在要给它添加Identity功能,还要让AspNetUsers和部分现有实体建立关联,当前数据库里没有任何Identity相关的表。
按照官方教程操作时,需要指定数据库上下文和用户上下文。我选了数据项目里的EventFinderContext(与Web应用同解决方案不同项目),并创建了新的用户上下文。脚手架生成完成后,出现重复的EventFinderContext类,导致模糊引用错误;尝试将两个类改为partial后,执行迁移又提示存在多个DbContext,必须指定要使用的上下文。
有建议从头新建包含Identity的项目,但工作量太大。现提出两个问题:
- 需要修改哪些内容才能让脚手架适配现有EF Core逻辑?
- Identity是否应该使用独立的专用上下文?考虑到要建立Identity实体与现有实体的关联,这看起来不太合理。
更新:添加Identity后的代码结构
数据项目(包含实体和迁移)
EventFinderContext.cs
namespace EventFinderData { public class EventFinderContext : DbContext { public DbSet<EventItem> EventItems { get; set; } public DbSet<EventCategory> EventCategories { get; set; } public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options) { } } }
Web应用项目 - VS/Identity生成的类
Areas\Identity\Data\EventFinderWebAppRazorContext.cs
namespace EventFinderWebAppRazor.Data; public class EventFinderWebAppRazorContext : IdentityDbContext<EventFinderWebAppRazorUser> { public EventFinderWebAppRazorContext(DbContextOptions<EventFinderWebAppRazorContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); } }
Areas\Identity\Data\EventFinderWebAppRazorUser.cs
namespace EventFinderWebAppRazor.Areas.Identity.Data; public class EventFinderWebAppRazorUser : IdentityUser { }
Program.cs
builder.Services.AddDbContextFactory<EventFinderContext>(options => options.UseSqlServer( builder.Configuration.GetConnectionString("EventFinderConnString"), ss => ss.UseNetTopologySuite()) .EnableSensitiveDataLogging()); builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>( options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<EventFinderWebAppRazorContext>();
问题1:修改内容适配现有EF Core逻辑
核心问题是两个独立DbContext导致冲突,正确做法是将Identity集成到现有EventFinderContext中,步骤如下:
修改现有上下文的继承关系
将EventFinderContext从DbContext改为继承IdentityDbContext<EventFinderWebAppRazorUser>,并确保能访问用户实体类:// 数据项目中的EventFinderContext.cs using EventFinderWebAppRazor.Areas.Identity.Data; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; namespace EventFinderData { public class EventFinderContext : IdentityDbContext<EventFinderWebAppRazorUser> { public DbSet<EventItem> EventItems { get; set; } public DbSet<EventCategory> EventCategories { get; set; } public EventFinderContext(DbContextOptions<EventFinderContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // 必须调用,否则Identity表无法生成 // 保留原有模型配置(如果有) } } }删除自动生成的Identity上下文
直接删除Web项目中的EventFinderWebAppRazorContext.cs,统一使用数据项目的上下文。调整Program.cs的服务配置
让Identity使用现有EventFinderContext:// Program.cs builder.Services.AddDbContextFactory<EventFinderContext>(options => options.UseSqlServer( builder.Configuration.GetConnectionString("EventFinderConnString"), ss => ss.UseNetTopologySuite()) .EnableSensitiveDataLogging()); builder.Services.AddDefaultIdentity<EventFinderWebAppRazorUser>( options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<EventFinderContext>(); // 改为使用EventFinderContext生成并执行Identity迁移
打开包管理器控制台,指定数据项目为启动项目,执行以下命令:Add-Migration AddIdentityToExistingContext -Context EventFinderContext Update-Database -Context EventFinderContext此操作会将Identity相关表添加到现有数据库,同时保留原有实体表。
问题2:Identity是否需要独立上下文?
不需要,除非项目有特殊架构需求(如多数据库分离)。
当需要建立Identity用户与现有实体的关联时(比如用户创建的EventItem),共享上下文是最优方案:
- 可直接在现有实体中添加用户导航属性与外键:
public class EventItem { // 原有属性 public int Id { get; set; } public string Title { get; set; } // 关联用户 public string CreatorId { get; set; } public EventFinderWebAppRazorUser Creator { get; set; } } - 共享上下文能保证事务一致性,例如创建
EventItem与更新用户信息可在同一事务中完成。
使用独立上下文会增加跨上下文关联的复杂度,还会导致事务管理困难,完全没必要。
内容的提问来源于stack exchange,提问作者EvilDr

