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

无法保存含图片的Primeng p-editor富文本到SQL,执行存储过程报错

问题描述

使用C# + Dapper将包含Base64大图片的富文本内容(Primeng p-editor的Notes字段)通过用户定义表类型[Test].[ut_InsertRequest]传递给SQL Server存储过程时,抛出异常:Invalid operation. The connection is closed。

  • 小图片(5KB左右)可正常保存,18KB图片转Base64后(请求体长度111KB)触发异常
  • 用户定义表类型[Test].[ut_InsertRequest]包含Notes NVARCHAR(Max)列
  • 核心代码片段:
var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Notes", typeof(string));

// Notes内容示例:<p><img src=\"data:image/jpeg;base64,/9j/4AAQSkZJ........xgf/9k=\"></p>

dt.Rows.Add(
    request.Id,
    request.Notes
);

using var conn = sqlDbConnectionService.GetIDbConnection();
var result = await conn.QueryAsync<Response>(
    "[Test].[usp_InsertRequest]",
    new
    {
        tvpRequests = dt.AsTableValuedParameter("[Test].[ut_InsertRequest]"),
        itemId = 101,
    },
    commandType: CommandType.StoredProcedure
);
解决方案

1. 显式打开数据库连接

Dapper默认会自动管理连接的打开/关闭,但大数据异步传输时,可能出现连接被提前释放的情况。显式打开连接可确保操作期间连接持续活跃:

using var conn = sqlDbConnectionService.GetIDbConnection();
await conn.OpenAsync(); // 显式打开连接
var result = await conn.QueryAsync<Response>(
    "[Test].[usp_InsertRequest]",
    new
    {
        tvpRequests = dt.AsTableValuedParameter("[Test].[ut_InsertRequest]"),
        itemId = 101,
    },
    commandType: CommandType.StoredProcedure
);

2. 增加命令超时时间

大Base64数据传输耗时较长,默认30秒的超时时间可能不够,手动设置更长的超时阈值:

var result = await conn.QueryAsync<Response>(
    "[Test].[usp_InsertRequest]",
    new
    {
        tvpRequests = dt.AsTableValuedParameter("[Test].[ut_InsertRequest]"),
        itemId = 101,
    },
    commandType: CommandType.StoredProcedure,
    commandTimeout: 60 // 设置60秒超时,可按需调整
);

3. 调整连接字符串的数据包大小

SQL Server默认数据包大小为4096字节,大Base64数据可能超出限制导致连接异常。将数据包大小设为最大值32767:

Server=YourServerName;Database=YourDBName;Integrated Security=True;Packet Size=32767;

4. 优化大文本传输方式(推荐)

Base64编码会使数据体积增加约33%,改用VARBINARY(MAX)传输字节数组可减少数据量并避免NVARCHAR处理的潜在问题:

步骤1:修改用户定义表类型

将Notes列类型改为VARBINARY(MAX):

ALTER TYPE [Test].[ut_InsertRequest] 
ALTER COLUMN Notes VARBINARY(MAX);

步骤2:C#代码中转换为字节数组

var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Notes", typeof(byte[])); // 改为字节数组类型

// 将HTML字符串转为UTF8字节数组
var notesBytes = Encoding.UTF8.GetBytes(request.Notes);
dt.Rows.Add(request.Id, notesBytes);

using var conn = sqlDbConnectionService.GetIDbConnection();
await conn.OpenAsync();
var result = await conn.QueryAsync<Response>(
    "[Test].[usp_InsertRequest]",
    new
    {
        tvpRequests = dt.AsTableValuedParameter("[Test].[ut_InsertRequest]"),
        itemId = 101,
    },
    commandType: CommandType.StoredProcedure
);

步骤3:存储过程中转换回字符串

如果需要将字节数组转回字符串使用,可在存储过程中转换:

CAST(Notes AS NVARCHAR(MAX))

5. 检查存储过程和目标表定义

确保存储过程中处理Notes字段时没有截断逻辑,且最终插入的目标表列类型也是NVARCHAR(MAX)或VARBINARY(MAX)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:35:36