Dapper如何处理SQL Server中的FileStream Dapper文件流数据操作

来源:这里教程网 时间:2026-02-21 17:33:27 作者:

Dapper 本身不直接支持 SQL Server 的

FILESTREAM
功能,但它可以配合 ADO.NET 原生能力完成 FileStream 数据的读写操作。关键在于:Dapper 负责参数传递和结果映射,而 FILESTREAM 的二进制流处理需通过
SqlFileStream
或常规
varbinary(max)
参数方式实现。

理解 FILESTREAM 在 Dapper 中的角色定位

SQL Server 的 FILESTREAM 是将大文件(如图片、文档)存储在 NTFS 文件系统中,同时在数据库中保留指向该文件的指针(

uniqueidentifier
)。Dapper 不提供对
SqlFileStream
类的封装,也不自动识别
varbinary(max) FILESTREAM
列——它只把列当作普通二进制字段处理。因此你需要手动控制流的打开、读写和关闭逻辑。

插入/更新时,若想启用 FILESTREAM 存储,必须确保表已启用 FILESTREAM,并且对应列为
varbinary(max) FILESTREAM
Dapper 可以传入
byte[]
Stream
(需配合自定义
IDbCommand
设置)作为参数,但底层仍依赖 ADO.NET 的
SqlParameter
配置
查询 FILESTREAM 列时,Dapper 默认返回
byte[]
;若数据很大,建议改用
SqlFileStream
按需读取,避免内存爆炸

插入 FILESTREAM 数据(带事务与路径获取)

插入 FILESTREAM 数据需要两步:先插入一条记录获取 FILESTREAM 路径(即

PathName()
),再用该路径创建
SqlFileStream
写入内容。Dapper 可用于执行这两步 SQL,但流操作要自己写。

第一步:用 Dapper 插入空记录(FILESTREAM 列为
0x
NULL
),并返回
ROWGUID
或主键
第二步:调用
SELECT [FileColumn].PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT()
获取路径和上下文
第三步:在同一个事务中,用
new SqlFileStream(path, context, FileAccess.Write)
写入原始字节流

注意:整个过程必须在显式开启的

SqlTransaction
中进行,且 Dapper 的
Execute
/
QuerySingle
方法需传入该事务对象。

读取 FILESTREAM 数据(避免全量加载)

直接用 Dapper 查询 FILESTREAM 列会把整个文件加载进内存(如

conn.QuerySingle<byte>(sql)</byte>
),不适合大文件。推荐方式是只查出路径和上下文,再用
SqlFileStream
流式读取。

用 Dapper 执行
SELECT FileData.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT()
得到流信息
SqlTransaction
内创建
SqlFileStream
,然后用
CopyTo
或分块
Read
输出到响应流、文件或内存缓冲区
务必在使用后调用
stream.Close()
,否则 SQL Server 可能锁住文件句柄

替代方案:用 varbinary(max) 绕过 FILESTREAM(适合中小文件)

如果文件普遍小于 1–2 MB,可放弃 FILESTREAM,直接用标准

varbinary(max)
列 + Dapper 简化操作:

插入:
conn.Execute("INSERT INTO Docs (Name, Content) VALUES (@name, @content)", new { name = "a.pdf", content = File.ReadAllBytes(path) })
读取:
byte[] data = conn.QuerySingle<byte>("SELECT Content FROM Docs WHERE Id = @id", new { id = 123 })</byte>
优点是零额外依赖、事务透明、Dapper 完全兼容;缺点是数据库体积增长快、备份变重

基本上就这些。Dapper 不是 FILESTREAM 的“开关”,而是你操作数据库的轻量管道——FILESTREAM 的复杂性仍在 ADO.NET 层,Dapper 只帮你更干净地拼 SQL 和传参。

相关推荐