You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从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

  1. 匹配Npgsql包版本
    确保Npgsql.EntityFrameworkCore.PostgreSQL包版本与.NET 8完全匹配(使用8.x系列,如8.0.4),通过NuGet更新:
    dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.4
    
  2. 清理旧迁移并重新生成
    原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
    
  3. 显式配置类型映射
    若实体中使用long或大整数类型,在OnModelCreating中明确指定PostgreSQL列类型:
    builder.Entity<YourEntity>()
           .Property(e => e.BigIntegerField)
           .HasColumnType("bigint");
    

针对第二个错误:设计时无法创建DbContext

  1. 添加设计时工厂类
    在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);
        }
    }
    
  2. 指定启动项目运行EF命令
    执行EF Core命令时,必须指定包含appsettings.json的Web项目作为启动项,避免工具无法读取连接字符串:
    dotnet ef migrations list --project AletheiaSoft.Infrastructure --startup-project AletheiaSoft.Web
    
  3. 简化DbContext构造函数
    确保ApplicationDbContext仅接收DbContextOptions<ApplicationDbContext>参数,无其他需要注入的服务(设计时工具无法解析复杂依赖链)。

验证步骤

  1. 确认所有Npgsql相关包版本为8.x
  2. 删除旧SQL Server迁移文件
  3. 生成并应用新的PostgreSQL迁移
  4. 运行dotnet ef dbcontext info验证设计时DbContext是否正常创建

内容的提问来源于stack exchange,提问作者Alp Emre Elmas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:54:56