2016-08-17 1 views
0

SqlDataReader을 통해 DataTable 개체를 채우고 작업을 중단 할 수 있습니다 (예 : 장기 실행 쿼리를 취소하려는 경우 u/i를 통해).C# : SqlDataReader의 DataTable에 인터럽트 기능을 추가 하시겠습니까?

불행히도 DataTable.Load()의 과부하에는 CancellationToken이 필요하지 않습니다.

이것을 달성하기위한 명확한 방법이 있습니까?

(내 유일한 생각은 스레드를 사용하고 Thread.Interrupt()이 트릭을 수행하는지 확인한 다음 Thread.Abort()인데 꽤 비우호적 인 것처럼 보입니다).

+0

는 수천 개의 행을 채우기 위해 밀리 초 걸립니다. 이보다 조건을 쿼리 자체에 넣을 수 있습니다. –

+0

@DheerajRoy 설명 할 수 있습니까? 나는 메타 데이터를 포함한 모든 것을 반환하는 데 오랜 시간이 걸리는 쿼리를 가지고있다. "조건을 쿼리에 넣는"방법은 무엇입니까? – CoderBrien

+0

SqlDataAdapter를 통해 DataTable RowChanged를 조사해야한다고 생각합니다. –

답변

0

SqlDataAdapter와 함께 사용하면 DataTable RowChanged 이벤트를 처리하고 예외를 throw하거나 InvalidOperationException을 throw하는 데이터 어댑터의 연결을 닫을 수 있습니다.

다음 예제 ( 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); 
    } 
} 

이 같은이 방법을 사용합니다 :

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

그런 다음 조작을 취소 할 수 있습니다

tokenSource.Cancel(); 
+0

, 내 경우에는'reader.ReadAsync()'를 원할 것입니다. 메타 데이터를 질의 결과에 기반하고 싶을 때 어떻게'CreateDataTable()'을 구현합니까? 감사! – CoderBrien

+0

다음과 같이 할 수있을 것입니다. DataTable dt = reader.GetSchemaTable();'reader는 SqlDataReader입니다. – Kinetic

+0

... 느린 쿼리에서 차단하려면 :-(나는 메타 데이터를 반환하는 데 몇 분이 걸릴 수 있습니다. (묻지 마십시오). – CoderBrien