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

如何将依赖SqlFileStream的代码迁移至.NET6+ Linux环境?

迁移.NET FILESTREAM代码到.NET 6+ Linux环境的最佳方案

问题背景

你之前的代码是这么用SqlFileStream访问SQL Server FILESTREAM的:

var result = CreateSQLQuery($@"select [{ColumnName}].PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() as context from [{TableName}] where Id = :id")
    .SetParameter("id", entity.Id)
    .UniqueResult<object[]>();
return new SqlFileStream((string) result[0], (byte[]) result[1], fileAccess);

但到了Linux环境就失效了——因为SqlFileStream是Windows专属实现,底层依赖SMB协议,完全不支持跨平台。针对.NET 6+的跨平台场景,最靠谱的替代方案是用SQL Server 2019+官方推出的FILESTREAM REST API,下面给你一步步说怎么实现。

具体实现步骤

1. 先配置SQL Server支持REST访问

首先得确保你的SQL Server是2019或更高版本,然后开启FILESTREAM的HTTP访问:

  • 打开SQL Server配置管理器,找到目标实例,启用「针对文件流的HTTP访问」
  • 设置共享名称和端口(默认8080),同时在SQL Server所在机器的防火墙里开放这个端口,让Linux服务器能访问到

2. 替换原有SqlFileStream代码逻辑

核心就是把原来的SMB文件流操作,改成HTTP请求读写,下面是具体的代码示例:

读取FILESTREAM数据
using System.Net.Http;
using System.Data.SqlClient;

public async Task<byte[]> ReadFilestreamDataAsync(Guid entityId, string connectionString)
{
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();
    // 必须在SQL事务内操作,保证数据一致性
    using var tx = await conn.BeginTransactionAsync();

    // 查询获取REST访问地址和事务上下文
    var cmd = new SqlCommand(@"
        SELECT 
            CONCAT('http://你的SQL服务器IP或域名:端口/', 
                   REPLACE([ColumnName].PathName(), '\', '/')) AS RestUrl,
            GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext
        FROM [TableName] 
        WHERE Id = @id", conn, tx);
    cmd.Parameters.AddWithValue("@id", entityId);
    
    using var reader = await cmd.ExecuteReaderAsync();
    await reader.ReadAsync();
    var restUrl = reader.GetString(0);
    var transactionContext = (byte[])reader.GetValue(1);

    // 用HttpClient发送GET请求读取数据,带上事务上下文头
    using var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Add("TransactionContext", Convert.ToBase64String(transactionContext));
    
    return await httpClient.GetByteArrayAsync(restUrl);
}
写入FILESTREAM数据
public async Task WriteFilestreamDataAsync(Guid entityId, byte[] data, string connectionString)
{
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();
    using var tx = await conn.BeginTransactionAsync();

    // 同样先获取REST地址和事务上下文
    var cmd = new SqlCommand(@"
        SELECT 
            CONCAT('http://你的SQL服务器IP或域名:端口/', 
                   REPLACE([ColumnName].PathName(), '\', '/')) AS RestUrl,
            GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext
        FROM [TableName] 
        WHERE Id = @id", conn, tx);
    cmd.Parameters.AddWithValue("@id", entityId);
    
    using var reader = await cmd.ExecuteReaderAsync();
    await reader.ReadAsync();
    var restUrl = reader.GetString(0);
    var transactionContext = (byte[])reader.GetValue(1);

    // 发送PUT请求写入数据
    using var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Add("TransactionContext", Convert.ToBase64String(transactionContext));
    
    var content = new ByteArrayContent(data);
    var response = await httpClient.PutAsync(restUrl, content);
    // 确保请求成功,失败直接抛出异常
    response.EnsureSuccessStatusCode();

    await tx.CommitAsync();
}

3. 几个关键注意点

  • 版本硬性要求:SQL Server必须是2019及以上,这是FILESTREAM REST API的最低支持版本
  • 事务必须存在:所有读写操作都要在SQL事务中执行,并且必须携带TransactionContext请求头,否则SQL Server会拒绝访问
  • HttpClient优化:如果频繁操作FILESTREAM,建议复用HttpClient实例(比如通过依赖注入注册为单例),避免频繁创建销毁带来的性能开销
  • 网络连通性:Linux服务器要能正常访问SQL Server的HTTP端口,提前检查防火墙、网络路由是否正常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 06:38:02