状況
多くのパラメーター化された SQL コマンドがあります。これらのコマンドをループ内で次々に実行すると、次のようになります。
public void SaveChanges()
{
using (var ts = _Context.Database.BeginTransaction())
{
try
{
_Context.SaveChanges();
foreach (var cmd in _Commands)
{
if (cmd.Parameter != null)
{
_Context.Database.ExecuteSqlCommand(cmd.Sql, cmd.Parameter.ToArray());
}
}
ts.Commit();
}
catch (Exception ex)
{
ts.Rollback();
throw new Exception("SaveChanges");
}
}
}
上記のコードは機能し、トランザクションのロールバックも期待どおりに機能します。
私のコマンドクラスは次のようになります。
public class SqlBuilderCommand
{
public string Sql { get; set; }
public List<SqlParameter> Parameter {get;set;}
}
具体的な解決策がない重複の可能性
この質問と重複する可能性のあるものをいくつか見つけました。最も近いものはこれです:
残念ながら、Entity Framework では役に立ちません (または理解できないだけです)。
質問
リスト内のすべてのコマンドを 1 回の往復で実行できますか?
そうでない場合、ADO.NET で可能ですか?
解決策と欠点/制限
正しい答えをくれた@Evgeniに感謝します。はい、多くのSQL文字列を連結して、パラメーターを1回の往復でリストとして送信するだけです。それは素晴らしいことです。
ただし、SQL-Server には制限があります。SQL-Server は、1 つのコマンドで最大 2100 個のパラメーターのみを受け入れます。したがって、7 つのデータベース列を持つオブジェクトがある場合、一括挿入の最大数はコマンドごとに 300 オブジェクトです。そうしないと、例外が発生します。
5000 個のオブジェクトに対してこれを行うと、17 個の一括挿入 (5000/300) が発生します。5000 個のオブジェクトの時間を停止しましたが、それでも 8 ~ 9 秒であり、これは遅すぎます。生の SQL の方がはるかに高速であることがわかっているからです。
この時点で、SQL コマンドを高速化する方法があると誰かに言われない限り、生の SQL を回避する方法はないと思います。
多分私はこれにフォローアップの質問を書きます. くそ。