2016-08-17 17 views
0

私はSqlDataReaderDataTableオブジェクトを記入し、操作を中断する能力を持っています(例えば、長い実行中のクエリをキャンセルしたい場合は、u/iを使用します)。C#:SqlDataReaderのDataTableに割り込み機能を実装しますか?

残念ながら、DataTable.Load()のオーバーロードは表示されず、CancellationTokenが必要です。

これを達成するためのきれいな方法はありますか?

(私の唯一の考えは、スレッドを使用して、Thread.Interrupt()がトリックを行うかどうかを確認し、そうでなければThread.Abort()ですが、それはかなり不公平です)。

+0

CancellationTokenSource tokenSource = new CancellationTokenSource(); Task.Factory.StartNew(() => FillTable(tokenSource.Token), tokenSource.Token); 

次にあなたが操作をキャンセルすることができます。これよりも条件をクエリ自体に入れることができます。 –

+0

@DheerajRoyあなたは説明できますか?私はメタデータを含む何かを返すために長い時間がかかるクエリを持っています。どのように私は "クエリの条件"を置くのですか? – CoderBrien

+0

私はSqlDataAdapter経由でDataTable RowChangedを調べるべきだと思います。 –

答えて

0

SqlDataAdapterと組み合わせて、DataTableのRowChangedイベントを処理し、例外をスローするか、InvalidOperationExceptionをスローするデータアダプタの接続を閉じることができます。

は、次の例(source)を見てみましょう:

private BackgroundWorker worker; 
private DataTable table; 

private void button2_Click(object sender, EventArgs e) 
{ 
    if (worker != null) 
    { 
    worker.CancelAsync(); 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    this.worker = new BackgroundWorker(); 
    worker.WorkerReportsProgress = true; 
    worker.WorkerSupportsCancellation = true; 

    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 

    worker.RunWorkerAsync(); 
} 

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    MessageBox.Show(this.table.Rows.Count.ToString()); 
} 

[System.Diagnostics.DebuggerStepThrough] 
void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    this.table = new DataTable(); 

    using (SqlConnection connection= new SqlConnection()) 
    using (SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM table", connection)) 
    { 
    table.RowChanged += new DataRowChangeEventHandler(table_RowChanged); 
    da.Fill(table);   
    } 
} 

[System.Diagnostics.DebuggerStepThrough] 
void table_RowChanged(object sender, DataRowChangeEventArgs e) 
{ 
    if (worker.CancellationPending) 
    { 
    throw new ApplicationException("Canceled"); // throw a spanner in the works 
    } 
    Thread.Sleep(5); // Just slow things down for testing 
} 
2

あなたはタスクとキャンセルトークンを使用することができます。もちろん、Loadメソッドを使用する代わりに、DataTableを手動で入力する必要があります。

private void FillTable(CancellationToken token) 
{ 
    var reader = new SqlDataReader(); 
    var dt = CreateDataTable(); 
    while(reader.Read() && !token.IsCancellationRequested) 
    { 
     var row = dt.NewRow(); 
     // fill row from reader.... 
     dt.Rows.Add(row); 
    } 
} 

あなたはこのように、このメソッドを使用します。それは数千行を埋めるためにミリ秒を要する

tokenSource.Cancel(); 
+0

私は、私は 'reader.ReadAsync()'がほしいと思います。どのように私は 'CreateDataTable()'私は、クエリ結果に基づいてメタデータをしたいの実装ですか?ありがとう! – CoderBrien

+0

私はこのようなことができると思います。 'DataTable dt = reader.GetSchemaTable();'ここで、readerはSqlDataReaderです。 – Kinetic

+0

...遅いクエリでブロックするのに戻る:-(私はメタデータを返すために数分かかるかもしれませんが(質問しません) – CoderBrien

関連する問題