我在将大量数据写入SQL Server上的FILESTREAM列时遇到问题。具体来说,1.5-2GB 左右的小文件处理得很好,但是当大小达到 6GB 及以上时,我在传输结束时.CopyTo()
时断断续续地IOException
"句柄无效"。
我考虑过将数据写入块,但是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;
}
我建议你在FileStream类周围使用BufferedStream Class。
还要确保在 SqlFileStream 类上设置 WriteTimeOut 属性。
在这里,您可以找到一篇非常好的帖子,它解释了有关SqlFileStream http://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/的所有内容
正如一些评论所建议的那样,问题可能是事务超时。您可以通过运行 SQL Server 事件探查器并监视要回滚的事务来验证这一点。
除非另有说明,否则 machine.config 的默认 maxTimeout 为 10 分钟,无法通过代码覆盖。 要增加最大超时,请将以下内容添加到计算机的配置设置中。
<system.transactions>
<machineSettings maxTimeout="00:30:00" />
</system.transactions>