从SQL Server切换至PostgreSQL时ApplicationDbContext创建及迁移报错求助
从SQL Server迁移到PostgreSQL时的EF Core错误排查与解决
背景
项目遵循Clean Architecture架构,原基于SQL Server开发,切换到PostgreSQL后出现两类错误:
第一个错误(初始化/迁移阶段)
AletheiaSoft.Infrastructure.Data.ApplicationDbContextInitialiser[0] 初始化数据库时发生错误。
System.TypeInitializationException: 'Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping.NpgsqlBigIntegerTypeMapping'的类型初始值设定项引发异常
禁用迁移和数据填充后,数据库连接可正常建立,但出现第二个设计时错误:
第二个错误(EF Core设计时工具报错)
Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time
相关代码
依赖注入配置
using AletheiaSoft.Application.Common.Interfaces; using AletheiaSoft.Domain.Constants; using AletheiaSoft.Infrastructure.Data; using AletheiaSoft.Infrastructure.Data.Interceptors; using AletheiaSoft.Infrastructure.Identity; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Configuration; namespace Microsoft.Extensions.DependencyInjection; public static class DependencyInjection { public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration) { var connectionString = configuration.GetConnectionString("PostgreSqlConnection"); Guard.Against.Null(connectionString, message: "Connection string 'DefaultConnection' not found."); services.AddScoped<ISaveChangesInterceptor, AuditableEntityInterceptor>(); services.AddScoped<ISaveChangesInterceptor, DispatchDomainEventsInterceptor>(); services.AddDbContext<ApplicationDbContext>((sp, options) => { options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>()); options.UseNpgsql(connectionString); }); services.AddScoped<IApplicationDbContext>(provider => provider.GetRequiredService<ApplicationDbContext>()); services.AddScoped<ApplicationDbContextInitialiser>(); services.AddAuthentication() .AddBearerToken(IdentityConstants.BearerScheme); services.AddAuthorizationBuilder(); services .AddIdentityCore<ApplicationUser>() .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddApiEndpoints(); services.AddSingleton(TimeProvider.System); services.AddTransient<IIdentityService, IdentityService>(); services.AddAuthorization(options => options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); return services; } }
ApplicationDbContext实现
using System.Reflection; using AletheiaSoft.Application.Common.Interfaces; using AletheiaSoft.Domain.Entities; using AletheiaSoft.Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace AletheiaSoft.Infrastructure.Data; public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<TodoList> TodoLists => Set<TodoList>(); public DbSet<TodoItem> TodoItems => Set<TodoItem>(); public DbSet<Client> Clients => Set<Client>(); public DbSet<Project> Projects => Set<Project>(); protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); } }
技术栈
- .NET 8.0
- PostgreSQL(注:当前PostgreSQL稳定版为16.x,用户标注的8.0应为笔误)
解决方案
针对第一个错误:TypeInitializationException
- 匹配Npgsql包版本
确保Npgsql.EntityFrameworkCore.PostgreSQL包版本与.NET 8完全匹配(使用8.x系列,如8.0.4),通过NuGet更新:dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.4 - 清理旧迁移并重新生成
原SQL Server迁移文件包含专属类型定义,需删除Infrastructure/Data/Migrations目录下所有旧文件,重新生成PostgreSQL迁移:dotnet ef migrations add InitialPostgreSqlSetup --project AletheiaSoft.Infrastructure --startup-project AletheiaSoft.Web dotnet ef database update --project AletheiaSoft.Infrastructure --startup-project AletheiaSoft.Web - 显式配置类型映射
若实体中使用long或大整数类型,在OnModelCreating中明确指定PostgreSQL列类型:builder.Entity<YourEntity>() .Property(e => e.BigIntegerField) .HasColumnType("bigint");
针对第二个错误:设计时无法创建DbContext
- 添加设计时工厂类
在Infrastructure项目中创建专属工厂,让EF Core设计时工具直接实例化DbContext:using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; namespace AletheiaSoft.Infrastructure.Data; public class ApplicationDbContextDesignTimeFactory : IDesignTimeDbContextFactory<ApplicationDbContext> { public ApplicationDbContext CreateDbContext(string[] args) { var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var options = new DbContextOptionsBuilder<ApplicationDbContext>(); options.UseNpgsql(config.GetConnectionString("PostgreSqlConnection")); return new ApplicationDbContext(options.Options); } } - 指定启动项目运行EF命令
执行EF Core命令时,必须指定包含appsettings.json的Web项目作为启动项,避免工具无法读取连接字符串:dotnet ef migrations list --project AletheiaSoft.Infrastructure --startup-project AletheiaSoft.Web - 简化DbContext构造函数
确保ApplicationDbContext仅接收DbContextOptions<ApplicationDbContext>参数,无其他需要注入的服务(设计时工具无法解析复杂依赖链)。
验证步骤
- 确认所有Npgsql相关包版本为8.x
- 删除旧SQL Server迁移文件
- 生成并应用新的PostgreSQL迁移
- 运行
dotnet ef dbcontext info验证设计时DbContext是否正常创建
内容的提问来源于stack exchange,提问作者Alp Emre Elmas
相关产品推荐
相关产品推荐

