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

如何在Docker中无需EF Core从.NET应用执行PostgreSQL SQL迁移建表

问题描述

通过Docker Compose部署.NET应用与PostgreSQL,已配置连接字符串:

"DefaultConnection": "Host=employees.database;Port=5432;Database=EmployeeManager;Username=postgres;Password=admin"

Docker Compose配置文件如下:

version: '3.4'

services:
  halfbitzadanie:
    image: ${DOCKER_REGISTRY-}xyz
    build:
      context: .
      dockerfile: xyz/Dockerfile
    ports:
      - "5000:5000"
      - "5001:5001"

  employees.database:
    image: postgres:latest
    container_name: employees.database
    environment:
      - POSTGRES_DB=EmployeeManager
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=admin
    volumes:
      - ./.containers/employees-db:/var/lib/postgresql/data
    ports:
      - 5432:5432

运行应用时出现错误:

relation "employees" does not exist

本地未使用Docker时应用运行正常,进入PostgreSQL容器后发现EmployeeManager数据库中无任何表。未使用Entity Framework,需要无需EF Core的数据库迁移/表创建方案。

无需EF Core的数据库初始化方案

方法1:.NET应用启动时执行SQL脚本(推荐)

在应用启动阶段自动执行预编写的建表SQL,确保数据库表存在:

  1. 编写建表SQL脚本(如CreateEmployeesTable.sql),放到项目目录中,右键文件→属性→设置复制到输出目录为「如果较新则复制」。
    示例SQL:
    CREATE TABLE IF NOT EXISTS employees (
        id SERIAL PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        position VARCHAR(50),
        hire_date DATE
    );
    
  2. 在Program.cs中添加执行脚本的逻辑(使用Npgsql或ADO.NET):
    using System.Data;
    using Npgsql;
    using Microsoft.Extensions.Configuration;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // 注册服务...
    
    var app = builder.Build();
    
    // 执行数据库初始化脚本
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
    using var conn = new NpgsqlConnection(connectionString);
    try
    {
        conn.Open();
        var scriptPath = Path.Combine(AppContext.BaseDirectory, "CreateEmployeesTable.sql");
        var sqlScript = File.ReadAllText(scriptPath);
        using var cmd = new NpgsqlCommand(sqlScript, conn);
        cmd.ExecuteNonQuery();
        Console.WriteLine("数据库表初始化完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"初始化数据库失败: {ex.Message}");
    }
    
    // 配置中间件...
    
    app.Run();
    
    注意:IF NOT EXISTS确保脚本重复执行不会报错,适合每次启动应用时都执行一次。

方法2:利用PostgreSQL Docker镜像的自动初始化特性

PostgreSQL官方镜像支持启动时自动执行指定目录下的脚本,仅在首次创建数据卷时执行:

  1. 在项目根目录创建init-db文件夹,将建表SQL脚本放入(如01-create-employees-table.sql,文件名前缀数字控制执行顺序)。
  2. 修改Docker Compose配置,添加脚本目录映射:
    employees.database:
      image: postgres:latest
      container_name: employees.database
      environment:
        - POSTGRES_DB=EmployeeManager
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=admin
      volumes:
        - ./.containers/employees-db:/var/lib/postgresql/data
        - ./init-db:/docker-entrypoint-initdb.d  # 新增此映射
      ports:
        - 5432:5432
    
    首次启动容器时,镜像会自动执行/docker-entrypoint-initdb.d下的所有.sql、.sh脚本。若需要重新执行,需先删除本地.containers/employees-db目录再重启容器。

方法3:手动执行SQL脚本(调试用)

临时调试时,可手动进入容器执行脚本:

  1. 进入PostgreSQL容器:
    docker exec -it employees.database psql -U postgres -d EmployeeManager
    
  2. 直接输入建表SQL,或导入本地脚本:
    • 先把本地脚本复制到容器内:
      docker cp CreateEmployeesTable.sql employees.database:/tmp/
      
    • 在容器内执行脚本:
      \i /tmp/CreateEmployeesTable.sql
      

内容的提问来源于stack exchange,提问作者user28273827332

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:03:12