2

私はC++プログラマーであり、.NETデータベースモデルに精通していません。私は通常、データベースからデータを読み取るためにIDataReaderOdbcDataReader、、OledbDataReaderまたは)を使用します。SqlDataReader大量のデータが必要な場合もありますがDataAdapter、ODBCなどのネイティブライブラリに存在するスクロール可能なカーソルの機能を実現するにはどうすればよいですか?


皆様のご回答ありがとうございましたが、お受けできない状況にあります。もちろん、これは私の問題を完全に説明できなかった私のせいです。削除された回答の1つにコメントとして説明します。

クライアント側プログラムとMSSQLの間のプロキシとして機能するプログラムを作成する必要があります。このライブラリには、次の要件があります。

  • 私のプログラムはMSSQL2000と互換性があるはずです
  • ユーザーから送信されるすべてのテーブルとクエリがわからないので、情報を追加してログを作成し、MSSQLに対して実行する必要があるため、次のような手法を使用するのは非常に困難です。クエリの順序フィールドまたはテーブルの主キーに基づきます(私の作品はすべて1つのデータベースにありますが、そのデータベースは巨大であり、時間の経過とともに変更される可能性があります)。
  • クライアントが必要とするのはデータの一部だけで、ほとんどのDBMSはサポートしていませんがLIMIT OFFSET、残念ながらMSSQLそれをサポートしてROW_NUMBERいません。また、サポートされてMSSQL2000いる場合は、プログラムロジックを理解する必要があり、SQLコマンドの解析が必要です(実際には私は解析ライブラリを作成していますboost::spiritが、それはネイティブコードであり、その機能についてはまだ100%確信がありません)。
  • 私は複数のクライアントを持っているかもしれませんが、それらによって送信されるクエリのほとんどは、いくつかの事前定義されたクエリの1つです(もちろん、ユーザーはカスタムクエリを送信しますが、すべてのクエリの約30%です)。そのカーソルとカスタムキャッシュを使用してクライアントに応答します。
  • サーバーマシンとそのMSSQL専用プログラムなので、サーバーとDBMSのすべての機能を使用して機能を実現したいと考えています。

だから今:

  • スクロール可能なカーソルを使用する際の問題は何ですか?なぜそれらを避ける必要があるのですか?
  • .NETでスクロール可能なカーソルを使用するにはどうすればよいですか?
4

4 に答える 4

3

SQL Serverでは、このようにページングされたクエリを作成できます。アプリケーションから簡単に処理できるページ番号。このタスクのためにカーソルを作成する必要はありません。

SQLServer2005以降の場合

SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY ID) AS ROW FROM TABLEA ) AS ALIAS 
WHERE ROW > 40 
AND ROW <= 49

SQLServer2000の場合

SELECT TOP 10 T.* FROM TABLA AS T WHERE T.ID NOT IN
    ( SELECT TOP 39 id from tabla order by id desc )
ORDER BY T.ID DESC

PD:SQLServer2000のサポートを含むように編集

于 2012-12-31T23:11:52.890 に答える
2

私は通常、DataReader.Read()ページングをサポートしていないDBでページングを実行するときに、使用したくないすべての行をスキップするために使用します。

SQLページクエリを自分で作成したくない場合は、私のページングクラスを自由に使用できます:https ://github.com/jgauffin/Griffin.Data/blob/master/src/Griffin.Data/BasicLayer/Paging/ SqlServerPager.cs

于 2013-01-03T08:16:20.080 に答える
2

MicrosoftがADO.NETAPIを設計したとき、Firehoseカーソル(IDataReaderなど)のみを公開することを決定しました。これは実際に問題を引き起こす場合とそうでない場合があります。「スクロール可能なカーソルの機能」が必要だとおっしゃっていますが、それはページングだけでなく、あらゆる種類のことを意味する可能性があり、それぞれの特定のユースケースはさまざまな方法で取り組むことができます。例えば:

要件:ユーザーは、結果セットを任意に上下にページアップできる必要があります。

  • 関数を使用するなど、一度に1ページのデータのみを取得しROW_NUMBER()ます。これは、カーソルをスクロールするよりも効率的です。

要件:非常に大きなデータセットがあり、メモリ不足を回避するために一度に1行だけを処理したいと考えています。

  • ADO.NETが提供するファイアホースカーソルを使用します。これは、(a)ループ中にデータベースにアクセスする必要がまったくない場合、または(b)接続文字列にMARSが構成されている場合にのみ実用的であることに注意してください。
  • 一意の識別子のセットを配列に取得してキーセットカーソルをシミュレートし、配列をループして一度に1行のデータを読み取ります。

要件:結果セットを前後に移動することを含む複雑な計算を行っています。

  • この要件を排除するために、アルゴリズムを書き直すことができるはずです。たとえば、ある行のセットを読み取り、それらを処理し、別の行のセットを読み取り、それらを処理します。

更新(質問で提供される詳細情報)

あなたのビジネス要件はあまりにも多くを求めています。スクロール可能なカーソルの存在を前提とする任意のクエリを処理する必要がありますが、スクロール可能なカーソルを提供することはできず、スクロール可能なカーソルを使用しないようにクライアントコードを書き直すことはできません。これは不可能な立場です。現在持っているもの(C ++とODBC)を使い続け、.NETでわざわざ書き直そうとしないことをお勧めします。

于 2013-01-03T08:29:18.650 に答える
2

特定のケースではカーソルが機能しないと思います。主な理由は、3つの層があることです。しかし、2歩戻りましょう。

ほとんどの3層アプリケーションには、ステートレス中間層(c ++コード)があります。キャッシングは、実際には単なる最適化であり、中間層に実際の状態を作成しないため、問題ありません。中間層には通常、データベースに対して少数のオープンセッションがあります。dbセッションを開くことはプロセッサにとってコストがかかり、dbセッションが開かれた後、一定量のRAMがデータベースサーバーに予約されるためです。中間層が要求を受信すると、要求が処理されてSQLデータベースに渡されます。アルゴリズムを使用して、開いているセッションのいずれかを選択することも、ランダムに実行することもできます。このモデルでは、どのセッションが次のリクエストを受け取るかを知ることはできません。カーソルは、元のクエリ要求を受信したセッションに属します。だからあなたはできる'

私が説明した3層モデルは、主にWebアプリケーションに使用されるため、数百または数千のクライアントに拡張できます。SQLサーバーがこれほど多くのセッションを開くことができなかったとしたら。Microsoft ADO.NETには、私が説明した種類のアーキテクチャをサポートするための多くの機能がすでに備わっているため、実装はそれほど難しくありません。また、状況によっては、Web以外のアプリケーションでも同じことが使用されます。セッションを追跡できる可能性があるため、クライアントごとに1つのセッションを開くことができます。まず、ユースケースがそれを正当化することを確認します。開いているカーソルも多くのリソースを消費する可能性があることを知っておいてください。

カーソルは単一のトランザクション内に配置されたままであり、クライアントアプリケーションが結果セット内の値をフェッチ/更新できるように、カーソルを開いたままにしておくのは困難です。

クエリトランザクション内で次のことを行うことをお勧めします。クエリのメインテーブルの主キー値を別のテーブルに保存します。別のテーブルには、sessionidやrownumberなどの他の値を含めます。元のクエリの新しいテーブルにリンクして、最初の行のいくつかを返します。その後の呼び出しでは、新しいテーブルにリンクして、対応する行を再度クエリします。古いデータを削除し、必要に応じて結果セットを更新するには、キャッシュメカニズムと同等の機能が必要になります。

于 2013-01-09T21:00:58.447 に答える