投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/2/28 09:48:08
> ただお値段が結構しますね..
BULK INSERT 自体はデータベース側の機能なので、
Dapper によるサポートが不要なら自分で呼び出す選択肢もあります。

あるいは後から紹介した、無料の Dapper.Bulk というものもありますが、Dapper.Plus と違って
>> 速度比較の記事が見当たらない
ので、こちらはその有効性が判断しにくいところ。


> テーブルにレコードをInsertした際にテーブル内のIdentityに設定している列に自動的に入ります。
Indentityによる自動採番だとして、α,β,γの主キー構造が単一主キーなのか、
それとも複合主キーなのか読み解けませんでした。
(βとγの繋がりが、データーベース的にどういうテーブル構成になっているのか?)


> αと同じようなことをするとデータベースへの接続を何度も繰り返すことになり非効率なのかなと思い、
IDENT_CURRENT / SCOPE_IDENTITY / @@IDENTITY 等を繰り返すような
カーソル処理・ループ処理は、SQL とは相性が悪いので、基本的には
一括処理できる設計で検討した方が良いとは思いますね。
データ量などいろいろな要件に左右されるので、一概には言えない所もありますが。


> Insert文の実行をした後にSelect文の実行をしてIdentityの値を取得しています。
複数テーブルあるいは複数レコードにまたがる自動採番の場合、
たとえば「予約番号」を使うという手法があります。

やり方は幾つかありますが、たとえば採番が 1~9999999999 という範囲で生成されるのなら、
挿入予定のデータ側には、それと被らない -1, -2, -3, -4, …… といった連番で割り当て、
それを一括登録した後、トランザクション処理の中で、負数を実際の採番値に
置き換えてからコミットするようにします。
(この手法を採る場合は、IDENTITY よりも SEQUENCE の方が扱いやすいかもしれません)

もし、VB 側が List や Array で管理されているのなら、
そこに連番を振るためのコストは、ほぼ無視できるでしょう。

しかし、後からキーを置換するというこの方法では、インデックスに対するロックが
広くかかりすぎてしまうという欠点もあります。

それを避ける場合、予約番号をコミット時に後から決めるのではなく、その逆に
先に必要な数だけ、データ登録準備段階で採番値の一覧をサーバー側に発行させてしまい、
それをローカル側で割り当ててから BULK INSERT とするというやり方もあります。

こちらの手法であれば、ロックも最小限で済みますし、tempdb への負荷も少なくて済みます。
その代わり、データベース側から採番値を事前に取得する手間が追加されるため、
実際には 3 層アーキテクチャ型のアプリケーション設計にしておき、ビジネスロジック層で
この変換処理を行うような実装とします。