【问题标题】:How to write large files to SQL Server FILESTREAM?如何将大文件写入 SQL Server FILESTREAM?
【发布时间】:2012-09-24 04:11:22
【问题描述】:

我在将 大量 数据写入 SQL Server 上的 FILESTREAM 列时遇到问题。具体来说,大约 1.5-2GB 的小文件可以很好地处理,但是当大小达到 6GB 及以上时,我会在IOException.CopyTo() 的末尾得到 intermittent @“句柄无效”转移。

我曾考虑以块的形式写入数据,但 SQL Server 在允许将数据附加到该字段之前复制了该字段的支持文件,这完全破坏了大文件的性能。

代码如下:

public long AddFragment (string location , string description = null) 
{
    const string sql = 
        @"insert into [Fragment] ([Description],[Data]) " +
            "values (@description,0x); " +
         "select [Id], [Data].PathName(), " +
             "GET_FILESTREAM_TRANSACTION_CONTEXT() " +
         "from " +
             "[Fragment] " +
         "where " +
             "[Id] = SCOPE_IDENTITY();";

    long id;

    using (var scope = new TransactionScope(
        TransactionScopeOption.Required, 
            new TransactionOptions {
                Timeout = TimeSpan.FromDays(1)
            })) 
    {
        using (var connection = new SqlConnection(m_ConnectionString)) 
        {
            connection.Open();

            byte[] serverTx;
            string serverLocation;

            using (var command = new SqlCommand (sql, connection)) 
            {
                command.Parameters.Add("@description", 
                    SqlDbType.NVarChar).Value = description;

                using (var reader = command.ExecuteReader ()) 
                {
                    reader.Read();
                    id = reader.GetSqlInt64(0).Value;
                    serverLocation = reader.GetSqlString (1).Value;
                    serverTx = reader.GetSqlBinary (2).Value;
                }
            }

            using (var source = new FileStream(location, FileMode.Open, 
                FileAccess.Read, FileShare.Read, 4096, 
                FileOptions.SequentialScan))
            using (var target = new SqlFileStream(serverLocation, 
                serverTx, FileAccess.Write))
            {
                source.CopyTo ( target );
            }
        }

        scope.Complete();
    }

    return id;
}

【问题讨论】:

  • 那里有一个通用示例,将 9 个字节写入该字段。
  • 可能是连接超时。例如,您是否尝试增加连接超时。顺便说一句,只是想知道,为什么要使用 SQL Server 来处理这么大的文件?这些天这是否成为 SQL Server 上的一种常见做法?
  • 到处都有超时。在 SqlCommand 以及事务上(您指定的 1 天超时不起作用,因为默认的最大超时为 10 分钟。您需要编辑一些配置文件来解决这个问题)。
  • 大文件处理需要使用BufferedStream,在企业应用中也可以使用。

标签: c# .net sql-server stream


【解决方案1】:

我建议你在 FileStream 类周围使用 BufferedStream 类。

还要确保在 SqlFileStream 类上设置 WriteTimeOut 属性。

在这里您可以找到一篇非常好的帖子,它解释了有关 SqlFileStream http://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/ 的所有内容

【讨论】:

  • 尽管有文档,但 WriteTimeout 不受支持,并且会从底层 Stream 抛出 InvalidOperationException,至少在 4.0 中
  • 很遗憾,也只是指出它不需要在 FileStream 上使用 bufferedstream,因为最近版本的 .net 缓冲功能已添加到 FileStream。
【解决方案2】:

正如一些 cmets 所建议的,问题可能是事务超时。您可以通过运行 SQL Server Profiler 并观察要回滚的事务来验证这一点。

除非另有说明,否则 machine.config 的默认 maxTimeout 为 10 分钟,不能通过代码覆盖。要增加最大超时,请将以下内容添加到 machine.config 的配置设置中

<system.transactions>
  <machineSettings maxTimeout="00:30:00" />
</system.transactions>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多