Dapperを使用して2100行(ID別)を削除する正しい方法

dapper parameters sql-server

質問

Dapperがサーバーアプリケーションのデータアクセスをサポートするようにしようとしています。

私のサーバーアプリケーションには、1分あたり400の割合でデータベースにレコードをドロップする別のアプリケーションがあります。

私のアプリはバッチでそれらを取り出し、処理した後、データベースから削除します。

私が処理している間はデータがデータベースに流れ続けているのでdelete from myTable where allProcessed = trueと言う良い方法はありません。

しかし、私は削除する行のPK値を知っています。だからdelete from myTable where Id in @listToDeleteたい

問題は、私のサーバーが6分でもダウンした場合、削除する行が2100を超えていることです。

Dapperは@listToDeleteを引数にとり、それぞれをパラメータに変換するので、deleteへの呼び出しは失敗します。 (私のデータ消去をさらに遅らせる原因となる)

Dapperでこれを処理する最善の方法は何ですか?

注:私は提出値のパラメータを見てきましたが、私が見ることができるものから、彼らは非常にではありませんパフォーマンス 。私の建築のこの部分は私のシステムのボトルネックです。私は非常速くする必要があります。

受け入れられた回答

1つの選択肢は、サーバー上に一時テーブルを作成し、バルクロード機能を使用してすべてのIDを一度にそのテーブルにアップロードすることです。次に、結合、EXISTSまたはIN句を使用して、一時表にアップロードしたレコードのみを削除します。

バルクロードはSQL Serverの最適化されたパスであり、非常に高速でなければなりません。

例えば:

  1. CREATE TABLE #RowsToDelete(ID INT PRIMARY KEY)ステートメントを実行して、
  2. #RowsToDelete一括読み込みを使用してキーを挿入する
  3. DELETE FROM myTable where Id IN (SELECT ID FROM #RowsToDelete)実行しDELETE FROM myTable where Id IN (SELECT ID FROM #RowsToDelete)
  4. DROP TABLE #RowsToDelte実行します(セッションを閉じるとテーブルも自動的に削除されます)

(Dapperを前提とする)コード例:

conn.Open();

var columnName = "ID";

conn.Execute(string.Format("CREATE TABLE #{0}s({0} INT PRIMARY KEY)", columnName));

using (var bulkCopy = new SqlBulkCopy(conn))
{
    bulkCopy.BatchSize = ids.Count;
    bulkCopy.DestinationTableName = string.Format("#{0}s", columnName);

    var table = new DataTable();                    
    table.Columns.Add(columnName, typeof (int));
    bulkCopy.ColumnMappings.Add(columnName, columnName);

    foreach (var id in ids)
    {
        table.Rows.Add(id);
    }

    bulkCopy.WriteToServer(table);
}

//or do other things with your table instead of deleting here
conn.Execute(string.Format(@"DELETE FROM myTable where Id IN 
                                   (SELECT {0} FROM #{0}s", columnName));

conn.Execute(string.Format("DROP TABLE #{0}s", columnName));

人気のある回答

このコードを動作させるには、私は暗いところに行った。

Dapperは私のリストをパラメータにするので。 SQL Serverでは多くのパラメータを処理できません。 (私は前に二桁のパラメータも必要としなかった)。私は動的SQLと一緒に行かなければならなかった。

だからここに私の解決策があった:

string listOfIdsJoined = "("+String.Join(",", listOfIds.ToArray())+")";
connection.Execute("delete from myTable where Id in " + listOfIdsJoined);

みんながトーチと干しぶどう酒を手に入れる前に、私に説明させてください。

  • このコードは、入力のみがメインフレームシステムからのデータフィードであるサーバー上で実行されます。
  • 私が動的に作成しているリストは、longs / bigintのリストです。
  • longs / bigintsはIdentity列のものです。

私はダイナミックSQLの構築が悪いことを知っていますが、この場合、セキュリティリスクにつながるのは分かりません。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ