2011-04-04 5 views
2

私はWCFデータサービス内で 'AsyncPattern'を実装しようとしています。私はインターフェイスでBeginGetExperiments(...)とEndGetExperiments(...)の2つのメソッドを定義し、以下に示すようにメソッドを実装します。SQL Serverを呼び出すサーバー側のAsyncPattern

public class GmdProfileService : IGmdProfileService 
{ 
IAsyncResult IGmdProfileService.BeginGetExperiments(AsyncCallback callback, object state) 
    { 
     //IAsyncResult res = Experiment.GetExperimentsAsync(callback, state, Properties.Settings.Default.gmdConnectionString); 
     //return res; 

     System.Data.SqlClient.SqlConnectionStringBuilder csb = new System.Data.SqlClient.SqlConnectionStringBuilder(Properties.Settings.Default.gmdConnectionString); 
     csb.AsynchronousProcessing = true; 
     System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(csb.ConnectionString); 
     conn.Open(); 
     System.Data.SqlClient.SqlCommand cmd = conn.CreateCommand(); 
     cmd = conn.CreateCommand(); 
     cmd.CommandText = "SELECT id, name, comment, date, doi FROM tf.TagList WITH(NOLOCK) WHERE proprietary=0;"; 
     cmd.CommandType = System.Data.CommandType.Text; 
     return new SqlCommandAsyncResult(cmd, callback, state); 
    } 

    public List<Experiment> EndGetExperiments(IAsyncResult result) 
    { 
     List<Experiment> res = new List<Experiment>(); 
     SqlCommandAsyncResult myresult = result as SqlCommandAsyncResult; 
     using (System.Data.SqlClient.SqlDataReader reader = myresult.cmd.EndExecuteReader(myresult.originalState as IAsyncResult)) 
     { 
      try 
      { 
       while (reader.Read()) 
       { 
        res.Add(new Experiment(reader)); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
      finally 
      { 
       // Closing the reader also closes the connection, because this reader was created using the CommandBehavior.CloseConnection value. 
       if (reader != null) 
       { 
        reader.Close(); 
       } 
      } 
     } 
     return res; 
    } 

BeginGetExperiments後でアクセスするための私のSqlCommandへの参照を保持していることに加えてIAsyncResultインタフェースを実装するクラスSqlCommandAsyncResultを返します。

私が直面する困難は、EndGetExperimentsの方法にあります。私はSqlCommandにアクセスしてEndExecuteReader(...)に電話する方法を知らない。 通常、私はBeginExecutereaderの状態オブジェクトを使用してコマンドを渡します。しかし、私がそうした場合、例外が発生します: "IAsyncResultの状態は、Begin呼び出しに渡される状態引数でなければなりません。"

IAsyncResultを使用して、SqlCommandをEndGetExperimentsに転送しようとしました。ここで、私が理解していない点は、EndGetExperimentsの場合、変数結果は、SqlCommandAsyncResultクラスのCompletedSynchronouslyの値に応じてタイプIAsyncResultまたはタイプSqlCommandAsyncResultのいずれかであることです。 CompletedSynchronously = falseを設定すると、SqlCommandにアクセスできないのでコードが失敗するCompletedSynchronously = trueコードは魅力的に機能しますが、何かが間違っている可能性があるという奇妙な感覚があります。

私は、このコードを動作させるための助けと指針とサンプルコードをお寄せいただきありがとうございます。

ありがとうございました。 Jan

答えて

1

C#4.0を使用している場合。これは達成するためにTask<T>を使用する方が簡単かもしれません。 Task<T>Func<T>を実行します。ここで、Tは戻り値です。 Parent.Resultをフェッチする継続タスクを定義できます。私はこの答えがあなたが探しているものではないかもしれないことを知っています。しかし、これを代替案と考えてください。このコードは、より洗練され、保守が容易で、デバッグが容易です(タスク並列ウィンドウ、並列スタックなどを使用)。

+0

@tonyjyありがとうございましたが、お勧めのパターンは、[OperationContractAttribute()のBeginMyMethod(...)EndMyMethod(...)パターンと互換性がありますか? AsyncPattern = true)] 'wcfデータサービス? – jahu

+0

私はそれがあなたが達成しようとしている目標に依存すると思います。 WCFに電話をかけている間にクライアントがブロックせずに実行されるようにしようとしている場合。サーバーは同期として実装でき、クライアントは非同期で使用できます。タスクは、TreadPoolまたはConcurrentContextのクライアント側で非常に便利です。 – tonyjy

+0

もう一度ありがとうございます。よくわかりません。上に掲げたコードは、明らかにサーバー側で実行されています。私が把握しようとしているのは、ベストプラクティステクノロジを使用してwcfデータサービスの**サーバー側**を実装して、SQlサーバーからデータを取り出してクライアントに転送する方法です。私はここに表示される 'AsyncPattern = true'に従います。[link](http://msdn.microsoft.com/en-us/library/ms731177.aspx)。これまでのところ、私はサーバー側についてしか話していません。 – jahu

関連する問題