10

データベースを更新するためにxmlファイルを読み取るようにコーディングしています。約 500 個の xml ファイルを取得し、できるだけ速く処理したいと考えています。

すべてのデータベース操作は、ストアド プロシージャを使用して行われます。

各 xml ファイルに対して呼び出される約 35 の異なるストアド プロシージャがあります。

最初に私はこのようなコードを書いていました

var cmd = new SqlCommand("EXEC UpdateTeamStats("+teamId+","+points+")");
cmd.CommandType = CommandType.Text;

しかし、いくつかのベストプラクティスを経た後、私はそれを

var cmd = new SqlCommand("UpdateTeamStats");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("teamId", 21);
cmd.Parameters.Add("points", 2);

プログラムから呼び出されるストアド プロシージャの数が多いため、最適化するために呼び出す回数を減らす必要があることに気付きました。

そのため、35 個のストアド プロシージャをすべてまとめて、一度に実行したいと考えています。

ストアド プロシージャはパラメーターによって異なり、上記で行ったパラメーターの変更後にそれらをまとめて実行する方法がわかりません。

私は 1 つの巨大なストアド プロシージャを呼び出し、そのストアド プロシージャ内で他の 35 を呼び出すことを考えていましたが、SQL があまり得意ではないため、不要な複雑さにつながります。

これを完全に C# で行うことは可能ですか?

または、ストアドプロシージャをキューに入れてすばやく実行するための他のより良い方法がありますか

4

4 に答える 4

1

最善の解決策は、xml ファイルごとのすべてのパラメーターのリストを含む、テーブル値パラメーターが渡された単一のストアド プロシージャを作成することです。次に、このストアド プロシージャで、テーブル値パラメーターの各レコードの他のすべてのストアド プロシージャを呼び出します。

これがうまくいかない場合は、ストアド プロシージャの代わりにテキスト型の SqlCommand を使用して、コマンドをビルドして実行することができます。現在と同じようにパラメーターを使用することも、動的 SQL を記述することもできます。

于 2012-04-25T09:39:13.687 に答える
1

から Microsoft アプリケーション データ ブロックをダウンロードしてください。

http://www.microsoft.com/download/en/details.aspx?id=435

いいけど、どうやって使うの?

このラッパー クラスの使い方は非常に簡単です。

DAC DC = new DAC();
DC.StoredProcedure = "nProc_InsertOrder";
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1" );
DC.Params.Add("@CustomerName", SqlDbType.VarChar, "test");
DAC.Commands.Add(DC);

DC = new DAC();
DC.StoredProcedure = "nProc_InsertOrderLineItems";
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1" );
DC.Params.Add("@OrderLineId", SqlDbType.VarChar, "A1");
DAC.Commands.Add(DC);

DC = new DAC();
DC.StoredProcedure = "nProc_InsertOrderLineItems";
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1" );
DC.Params.Add("@OrderLineId", SqlDbType.VarChar, "A2");
DAC.Commands.Add(DC);

DC = new DAC();
DC.StoredProcedure = "nProc_CreateBill";
DC.Params.Add("@BillDate", SqlDbType.DateTime, DateTime.Now);
DC.Params.Add("@BillId", SqlDbType.VarChar, "Bill1");
DAC.Commands.Add(DC);
DAC.ExecuteBatch();

注文の挿入が失敗した場合、請求書は作成されません。同様に、ラインアイテムが失敗した場合、オーダーは作成されません。これは、ADO.Net を使用してわずか数行のコードで実現しています。

この例では、ExecuteBatch を呼び出すまで、実際にレコードを挿入するのではなく、バッチ更新を行うためにオブジェクトを準備します。

于 2012-04-24T13:25:14.377 に答える
0

Command パターンCommandQueueを介してを作成し、コマンドでデリゲートを作成して、ストアド プロシージャの呼び出しに対する要件に対応させることができます。見た目では、次のようなものです:

public class CommandQueue
{
    private Connection _connexion = new Connection(); // Set this up somehow.

    // Other methods to handle the concurrency/ calling/ transaction etc.

    public Func<string, Dictionary<string, int>, bool> CallStoredProcedure = (procedureName, parameterValueMap) =>
    {
      cmd.Connection = GetConnexion();
      var cmd = new SqlCommand(procedureName);
      cmd.CommandType = CommandType.StoredProcedure;

      foreach (var parameterValueMapping in parameterValueMap)
      {
        cmd.Parameters.Add(parameterValueMapping.Key, parameterValueMapping.Value);
      }

      var success = cmd.ExecuteNonQuery();

      return success;
    }

    private Connection GetConnexion()
    {
      return _connexion;
    }
}

次に、 をセットアップしてCommandQueue、スレッドのプールを用意し、そこから新しいスレッドでデリゲートを呼び出して、並列で実行できるようにします。

実際、SQLCommandクラスを見ると、非同期呼び出しを行うことができます。Cancel()そのため、各ストアド プロシージャを非同期で呼び出し、それぞれが完了したときにデリゲートを設定し、すべてをトランザクションにラップして、必要なときに各コマンドを呼び出してロールバックできるようにする必要があります。CommandQueueおそらく後で変更することをお勧めするので、これを抽象化するためにおそらくまだ a を使用します。

ストアド プロシージャの呼び出しを のデリゲートでカプセル化すると思います。これにより、ストアド プロシージャCommandQueueの詳細が抽象化され、プロセスが他の人にとって理解しやすくなり、維持しやすくなります。新しいストアド プロシージャを追加したり、名前を変更したりすると、はるかに簡単になります。すべてのデリゲートを含む静的リストを設定するか、必要なストアド プロシージャの詳細を含む静的リストを設定し、デリゲートを使用してパラメーターのみを渡すことができます。

于 2012-04-19T10:08:45.813 に答える