我编写了一个自定义Stream类,需要访问数据库来读/写信息。我想使用XxAsync数据库方法,因此我建议在流中编写同步和异步方法,因为我在同步读/写方法中无法使用connection.OpenAsync()
。
然而,在实现两个版本之后,当我在一个简单的控制台应用程序的void Main()方法中使用此流作为调用中的目标时:
Task.Run( async () =>
{
using ( var ctx = new JobContext() )
{
// create AssemblyCache record and get assemblyKey...
using ( var fs = new System.IO.FileStream( @"C:\BTR\Source\Assemblies\BTR.Rbl.Evolution.Documents.dll",
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.None,
8192,
true ) )
using ( var bs = ctx.GetBinaryWriteStream<AssemblyCache>( assemblyKey ) )
{
await fs.CopyToAsync( bs );
}
}
} ).Wait();
似乎永远不会调用我的XxAsync方法。我只跟踪同步版本。看一下Stream基类的来源,看起来像CopyToAsync应该调用我的WriteAsync方法,所以我不确定我错过了什么。
更新
事实证明,我的GetBinaryWriteStream
扩展程序(故意)在我的自定义流周围包裹GZipStream
以支持压缩。 GZipStream
是未调用WriteAsync
的原因。我已经问了一个针对此here
答案 0 :(得分:2)
您可以使用SqlClient's streaming support将数据从客户端流式传输到服务器上的BLOV(即varbinary(MAX))列。您使用与用于执行INSERT的几乎相同的代码,但不是使用将值传递给SQL命令,而是传递流或流读取器。例如,而不是使用
var sql="INSERT INTO [MyTable] (blobField) VALUES (@data)"
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("@data", SqlDbType.Binary, myBuffer.Length).Value = myBuffer;
await conn.OpenAsync();
await cmd.ExecuteNonQueryAsync();
}
你会写
var sql="INSERT INTO [MyTable] (blobField) VALUES (@data)"
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
await conn.OpenAsync();
using (FileStream file = File.Open("binarydata.bin", FileMode.Open))
{
cmd.Parameters.Add("@data", SqlDbType.Binary, -1).Value = file;
await cmd.ExecuteNonQueryAsync();
}
}
如果要发送许多文件,可以在循环中为参数分配流:
var blobParam=cmd.Parameters.Add("@data", SqlDbType.Binary, -1);
foreach(var somePath in aListOfPaths)
{
using (FileStream file = File.Open(somePath, FileMode.Open))
{
blobparam.Value = file;
await cmd.ExecuteNonQueryAsync();
}
}
答案 1 :(得分:0)
事实证明,我的GetBinaryWriteStream
扩展名(有意地)在我的自定义流周围包装了GZipStream
以支持压缩。 GZipStream
是未调用WriteAsync
的原因。我问了一个专门针对此here