Stream.CopyToAsync从不调用我的WriteAynsc方法

时间:2016-09-07 15:23:07

标签: c# async-await filestream

我编写了一个自定义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

的新问题

2 个答案:

答案 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

的新问题