2016-08-29 7 views
0

私はStreamから派生したクラスを持っており、その読み書きではデータベースをヒットする必要があります。私は、SQLDATAオブジェクトの*非同期メソッドを使用していたが、その後のもちろん、それは私がこの(と思う)のようなものに非同期修飾子を持つように読むの署名を変更したい:他の*カスタムストリームクラスの非同期メソッドを呼び出す

public async override Task <int> Read(byte[] buffer, int offset, int count) 

そして、それがありません実際の署名と一致するので、コンパイルエラーメッセージが表示されます。このストリームの中で* Asyncを使ってどのように取り除くことができたのか、私はそれを同期したままにしておくべきですか?

私はまた、私のクラスはhttp://www.syntaxwarriors.com/2013/stream-varbinary-data-to-and-from-mssql-using-csharp/から最もアイデアをSQL ServerでVARBINARY(MAX)のフィールドにしてから、データのストリーミングを可能にされhttps://blogs.msdn.microsoft.com/pfxteam/2011/01/15/asynclazyt/

からスティーブンToubのAsyncLazyを使用。ここ

は(コメントアウト非同期ビットで)コードに興味深いビットである:

public class BinaryDataStream<T> : Stream 
{ 
    /* Async */Lazy<SqlDataReader> lazyReader; 
    SqlConnection connection; 
    SqlCommand firstUpdate; 
    SqlCommand otherUpdates; 
    long position; 

    public BinaryDataStream(DbContext context, string tableName, string keyName, string columnName, T keyValue) 
    { 
     connection = new SqlConnection(context.Database.GetDbConnection().ConnectionString); 

     lazyReader = new /* Async */Lazy<SqlDataReader>(/* async */() => 
     { 
      using (var cmd = new SqlCommand($"SELECT TOP 1 [{columnName}] FROM [dbo].[{tableName}] WHERE [{keyName}] = @id", connection)) 
      { 
       cmd.Parameters.AddWithValue("@id", keyValue); 
       /* await */ connection.Open/* Async */(); 

       var r = /* await */ cmd.ExecuteReader/* Async */(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow | System.Data.CommandBehavior.CloseConnection); 
       r.Read(); 

       return r; 
      } 
     }); 

     firstUpdate = new SqlCommand($"UPDATE [dbo].[{tableName}] SET [{columnName}] = @firstchunk WHERE [{keyName}] = @id", connection); 
     firstUpdate.Parameters.AddWithValue("@id", keyValue); 
     firstUpdate.Parameters.AddWithValue("@firstchunk", new byte[] { }); 

     otherUpdates = new SqlCommand($"UPDATE [dbo].[{tableName}] SET [{columnName}].WRITE(@chunk, NULL, @length) WHERE [{keyName}] = @id", connection); 
     otherUpdates.Parameters.AddWithValue("@id", keyValue); 
     otherUpdates.Parameters.AddWithValue("@length", 0); 
     otherUpdates.Parameters.AddWithValue("@chunk", new byte[] { }); 
    } 

    public /* async */ override /* Task< */int/* > */ Read(byte[] buffer, int offset, int count) 
    { 
     var reader = /* await */ lazyReader.Value; 
     var bytesRead = reader.GetBytes(0, position, buffer, offset, count); 
     position += bytesRead; 
     return (int)bytesRead; 
    } 

    public /* async */ override void Write(byte[] buffer, int offset, int count) 
    { 
     if (count == 0) return; 

     /* await */ connection.Open/* Async */(); 

     try 
     { 
      if (firstUpdate != null) 
      { 
       firstUpdate.Parameters[ "@firstchunk" ].Value = buffer; 
       /* await */ firstUpdate.ExecuteNonQuery/* Async */(); 
       firstUpdate = null; 
      } 
      else 
      { 

       var chunk = buffer; 
       if (count < buffer.Length) 
       { 
        chunk = new byte[ count ]; 
        Array.Copy(buffer, 0, chunk, 0, count); 
       } 

       otherUpdates.Parameters[ "@chunk" ].Value = chunk; 
       otherUpdates.Parameters[ "@length" ].Value = count; 
       /* await */ otherUpdates.ExecuteNonQuery/* Async */(); 
      } 
     } 
     finally 
     { 
      connection.Close(); 
     } 
    } 
} 
+1

'Wait'または' Result'を呼び出すと、デッドロックが発生する可能性があります。非同期のものをラッピングして同期バリアントを実装しようとしないでください。同期バージョンの場合、同期はすべて終了します。 (そして、非同期のための非同期メソッド)[非同期メソッドの同期ラッパーを公開する必要がありますか?](https://blogs.msdn.microsoft.com/pfxteam/2012/04/13/should-i-expose-synchronous- wrappers-for-asynchronous-methods /) –

+0

なぜ非同期メソッドを使いたいのですか? –

+0

dbクラスの* Async()メソッドを使用したい理由を尋ねるのであれば、私は「仮定された」と仮定しました。任意のIOのもの、私は今お勧めは、 'await * Async()'を可能な限り使用することだと思った? – Terry

答えて

2

Streamクラスがそのメソッドの同期および非同期の両方のバージョンを持っています。同様に、実行中のデータベース操作では、メソッドの同期バージョンと非同期バージョンの両方が公開されます。同期実装で同期メソッドをオーバーライドし、非同期実装を非同期実装でオーバーライドします。

+0

基本的に、非同期のdbオペレーションを使用すると、呼び出し元は自分のStreamクラスの非同期メソッドを使用する必要がありますか? – Terry

+0

@Terry Correct – Servy

+0

これは、私たちが 'NotSupportedException'を持っている理由です: –

関連する問題