2012-01-25 14 views
6

実行中のリーダーを停止することはできますか?読み取り中にデータリーダーを中断できますか?

シナリオ:100000データ

CREATE TABLE stock (
uid bigint NOT NULL, 
name text, 
quantity integer, 
x bytea, 
y bytea 
); 

、コンソールアプリケーション(.NET 4.0、Npgsqlの2.0.11.0/2.0.11.92)を設定すると、私はテーブルを持っているデータを読み出すための

conn = new NpgsqlConnection("Server=localhost;Database=postgres;User id=postgres;password=postgres;Timeout=600;CommandTimeout=600;ConnectionLifeTime=600;"); 
using (new ConnectionOpen(conn)) 
using (var ta = conn.BeginTransaction(IsolationLevel.Snapshot)) 
{ 
    IDbCommand command = conn.CreateCommand("SELECT * from stock;"); 
    command.SetTransaction(ta); 
    IDataReader reader = command.ExecuteReader(); 

    int n = 0; 
    while (!reader.IsClosed && reader.Read()) 
    { 
     n++; 

     if (n > 5000) 
     { 
      if (reader != null) 
      { 
       ((NpgsqlDataReader)reader).Close(); 
      } 
     } 
    } 
    ((NpgsqlDataReader)reader).Dispose(); 
    reader = null; 
} 

I実際に停止することはできませんデータリーダーを観察している。それは、データリーダーが最初にすべての行を読み取り、その後正常に返すようです。

この例は、読み取りに時間がかかりすぎるため、ボタンを押してデータリーダーを停止する大きなアプリケーションの要約です。

答えて

0

whileループにブレークを入れることはできますが、読んだループから抜け出すタイミングを決めるために、ユーザーアクションにそれを結び付けるかどうかはわかりません。あるいは、最初のx個の行を返すようにコードを再構成し、残りの行を返すための続行ボタンを与えたり、次のx個の行を返すようにすることができます。

0

これは推測です。

解決策1

... 
using (var ta = conn.BeginTransaction(IsolationLevel.Snapshot)) 
{ 
    IDbCommand command = conn.CreateCommand("SELECT * from stock;"); 
    command.SetTransaction(ta); 
    IDataReader reader = command.ExecuteReader(); 

    int n = 5000; 

    //put it in using 
    using(IDataReader reader = command.ExecuteReader()) 
    { 
     //read first N rows 
     for(int i=0;i<n;i++) 
     {   
      //get value from the columns of the current row 
      for (i = 0; i < reader.FieldCount; i++) 
      { 
       Console.Write("{0} \t", reader[i]); 
      } 
     } 
    }  
} 

可能sollution 2

使用TOP SQLコマンド、see samples

+0

:上記情報の

部品から取得されました。私のシナリオでは、データリーダーの動作を確認するためのログ出力は、コマンド "((NpgsqlDataReader)reader).Close()"の後、常に待ち時間を示します。この待ち時間は、すべての行を読み出すとほぼ同じです。 – Joerg

+0

!true && falseはfalseと評価されます。 !true XOR falseは真と評価されます。 –

+0

そうです、これを更新します。 – oleksii

0

データリーダは、典型的には、少なくとも(データベース・サーバからのデータのチャンクを返しますそれがSQL Serverとどのように機能するのか)。 PostgreSQLは、カバーの下で動作が異なる場合があります。

これを攻撃する別の方法は、バックグラウンドタスクとしてデータをロードすることです(BackgroundWorkerTaskなど)。そうすれば、あなたのUIスレッドは応答性があり、読者がどのようにカバーの下に実装されているかは関係ありません。

+0

私は、BackgroundWorkerがコンソールアプリケーションで動作するとは思わない。 – LarsTech

+0

私はそれをしました。しかし、ユーザーは最初のデータ行を読み込んで表示する際に、異なるデータで新しいクエリを開始することがあります。そして、今私はデータリーダーを停止し、新しいコマンドrespを開始する必要があります。データリーダー。 – Joerg

6

私はこのスレッドがかなり古いですが、私は次のようにこの人の質問に対する正しい答えがあると信じて知っている:)

command.Cancel(); //execute before closing the reader 
reader.Close(); 

をDbCommand.Cancel(呼び出すことにより、あなたはありませんさらに、レコードがすべきことを示しています処理され、コマンド(基礎となるクエリを含む)が即座に停止し、迅速に出て行くべきであるということです。コマンドをキャンセルせずにDbDataReaderを閉じる(またはループ/ブロックを中断する)ときに、返されるレコードの数が多い場合、Close()メソッドは出力パラメーター、戻り値、およびRecordsAffectedの値。

すべてのレコードを読み込む前に読者を閉じようとすると、Closeはすべてのデータを読み込み、それらの値を書き込もうとしますが、ちょうどハングしているように見えます。投げられた)。結果セットの残りの値を気にしないで、読み込みループから抜け出していない場合は、Close()を呼び出す前に基になるコマンドをキャンセルする必要があります。私は私のシナリオでは、ログ出力を残していhttps://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610

+0

これが答えです –

関連する問題