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

如何借助.NET EF迁移在PostgreSQL中提取大对象并植入新表?

解决方案:通过EF迁移提取PostgreSQL大对象中的JSON并生成新表

针对你的需求,这里提供两种实用的实现方式,均能兼容EF迁移的版本管控流程,无需额外复杂脚本或存储过程:


方案一:纯SQL数据库端处理(推荐,性能更优)

利用PostgreSQL内置的大对象操作与JSON解析函数,直接在迁移的Sql()方法中完成数据提取与插入,完全符合EF迁移的纯SQL操作模式,无需.NET内存中转数据。

步骤与代码示例

  1. 先创建新表的迁移(执行Add-Migration CreateTargetJsonTable),EF会自动生成新表的创建代码。
  2. 在迁移类的Up()方法中添加自定义SQL,读取大对象、解析JSON并插入新表:
protected override void Up(MigrationBuilder migrationBuilder)
{
    // EF自动生成的新表创建代码
    migrationBuilder.CreateTable(
        name: "TargetJsonData",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
            ItemName = table.Column<string>(nullable: false),
            ItemValue = table.Column<decimal>(nullable: false),
            CreateTime = table.Column<DateTime>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_TargetJsonData", x => x.Id);
        });

    // 自定义SQL:读取大对象中的JSON并插入新表
    migrationBuilder.Sql(@"
        -- 假设存储大对象OID的表为SourceLargeObjects,OID字段为lo_oid
        INSERT INTO TargetJsonData (ItemName, ItemValue, CreateTime)
        SELECT 
            json_item->>'item_name'::varchar AS ItemName,
            (json_item->>'item_value')::decimal AS ItemValue,
            (json_item->>'create_time')::timestamp AS CreateTime
        FROM SourceLargeObjects,
             -- 解析大对象中的JSON数组(若为单个JSON对象,去掉jsonb_to_recordset)
             jsonb_to_recordset(jsonb_in(lo_get(lo_oid))) 
             AS json_item(item_name varchar, item_value text, create_time text)
        WHERE lo_oid IS NOT NULL;
    ");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    // 回滚时直接删除新表,原大对象数据不受影响
    migrationBuilder.DropTable(
        name: "TargetJsonData");
}

优点

  • 完全适配EF迁移的管控流程,版本升降无额外复杂度
  • 数据在数据库端处理,避免跨网络传输,性能更优
  • 无需依赖.NET业务逻辑,迁移执行更稳定

方案二:.NET代码解析后插入(适合复杂JSON结构)

如果JSON结构嵌套复杂、需要自定义业务逻辑解析,可以在迁移的Up()方法中直接编写.NET代码,通过DbContext读取大对象、解析JSON后插入新表。

步骤与代码示例

  1. 创建新表的迁移(同方案一)。
  2. 在迁移类的Up()方法中添加自定义.NET逻辑:
protected override void Up(MigrationBuilder migrationBuilder)
{
    // EF自动生成的新表创建代码
    migrationBuilder.CreateTable(
        name: "TargetJsonData",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
            ItemName = table.Column<string>(nullable: false),
            ItemValue = table.Column<decimal>(nullable: false),
            CreateTime = table.Column<DateTime>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_TargetJsonData", x => x.Id);
        });

    // 自定义.NET逻辑:读取大对象、解析JSON并插入
    using var serviceProvider = new ServiceCollection()
        .AddDbContext<YourAppDbContext>(options =>
            options.UseNpgsql(migrationBuilder.GetService<IConfiguration>().GetConnectionString("DefaultConnection")))
        .BuildServiceProvider();

    using var context = serviceProvider.GetRequiredService<YourAppDbContext>();
    var sourceRecords = context.SourceLargeObjects.ToList();

    foreach (var record in sourceRecords)
    {
        if (record.LoOid == null) continue;

        // 读取PostgreSQL大对象内容
        using var loStream = context.Database.GetDbConnection().OpenLoStream((long)record.LoOid);
        using var reader = new StreamReader(loStream, Encoding.UTF8);
        var jsonContent = reader.ReadToEnd();

        // 解析JSON(示例为数组结构,可根据实际调整)
        var jsonItems = JsonSerializer.Deserialize<List<TargetJsonData>>(jsonContent, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        });

        if (jsonItems != null)
        {
            context.TargetJsonData.AddRange(jsonItems);
        }
    }

    context.SaveChanges();
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.DropTable(
        name: "TargetJsonData");
}

优点

  • 支持复杂JSON结构的自定义解析,适配特殊业务逻辑
  • 完全集成在EF迁移流程中,无需额外脚本管控

关键注意事项

  1. 权限验证:确保数据库用户拥有lo_get()函数的执行权限,以及大对象的读取权限
  2. 测试验证:在测试环境先执行迁移,确认数据解析与插入的准确性
  3. 事务控制:EF迁移默认在事务中执行,若数据量极大,可考虑拆分迁移或调整事务隔离级别

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:43:21