1

データベースへのすべての呼び出しに使用するメソッドを持つ「DButil」クラスがあるのでDataSet QueryDB(string spName, DBInputParams inputParams)、トランザクション呼び出しをサポートするためにこのメソッドを再利用したいと思います。

したがって、最後にSqlTransaction内にSqlDataAdapter.Fillがあります。これは悪い習慣ですか?トランザクション内でDataAdapter.Fillが使用されることはめったになく、ExecuteReader()が頻繁に使用されるためです。キャッチはありますか?

Edit1:重要なのは、トランザクション内でいくつかのデータ(自動IDなど)も取得する必要があることが多いということです...そのため、DataSetとして取得したいと思います。

Edit2:奇妙なことに、2つの異なるプロセスからのforループ(10000)でこのアプローチを使用すると、「トランザクション(プロセスID 55)が別のプロセスのロックリソースでデッドロックされ、デッドロックの犠牲者として選択されました。トランザクションを再実行してください。 。」。これは正しい動作ですか?

Edit3 :( Edit2の回答)エラーの原因となったものを使用しIDENT_CURRENT('XTable')ていました。に戻った後SCOPE_IDENTITY()、すべてが解決されました。

4

2 に答える 2

2

トランザクションが開いている間は、変更を加えたレコード/ページ/テーブルがトランザクションの間ロックされるため、これは悪い習慣です。塗りつぶしにより、プロセス全体でこれらのリソースがより長くロックされたままになります。SQL設定によっては、これらのリソースへの他のアクセスがブロックされる可能性があります。

とは言うものの、それが必要な場合、それは必要であり、それを行うことに対するペナルティを理解するだけです。

于 2011-06-09T15:54:34.227 に答える
2

それは悪い習慣ではありません。覚えておくべきことの1つは、すべてのステートメントが暗黙のトランザクションを使用し、ステートメントが終了すると自動的にコミットすることです。つまり、(Fillで使用されるSELECTのように)SELECTは常にトランザクションを使用します。問題は、それ自体でトランザクションを開始する必要があるのか​​、既存のトランザクションを使用するのかということです。

暗黙的なトランザクションと明示的なトランザクションでSELECTによって取得されるロックの数、タイプ、および期間に違いはありますか?デフォルトのトランザクションモデル(READ COMMITTED分離)NOでは、何もありません。動作は同じで、区別できません。他の分離レベル(繰り返し可能な読み取り、シリアル化可能)では違いがありますが、それは目的のより高い分離レベルが発生するために必要な違いであり、必要に応じて、明示的なトランザクションを使用することがこの目的の分離レベルを達成する唯一の方法です。

さらに、あなたの例のように(生成されたIDを読み戻す)、SELECTが保留中の(まだコミットされていない)トランザクションの効果を読み取らなければならない場合、他の方法はありません。SELECTは、IDを生成したトランザクションの一部である必要があります。そうでない場合、コミットされていないIDを表示できません。

ただし、注意が必要です。このすべてのトランザクション処理をはるかに簡単にすることができる優れたツールであるSystem.Transactionsを自由に使用できると思います。すべてのADO.Netコードはシステムトランザクションに対応しており、単に。を宣言すると、接続とコマンドが保留中のトランザクションに自動的に登録されますTransactionScope。つまり、関数FooがaTransactionScopeを宣言してから関数Barを呼び出す場合、BarがADO.Net操作を実行すると、Barが明示的に何もしなくても、自動的にFooで宣言されたトランザクションの一部になります。はTransactionScopeスレッドコンテキストにフックされ、Barによって呼び出されるすべてのADO.Net呼び出しは、このコンテキストを自動的にチェックして使用します。私は本当に何かを意味することに注意してください ADO.Net call, including Oracle provider ones. Alas though there is a warning: using new TransactionScope() Considered Harmful: the default constructor of TransactionScope will create a serializable transaction, which is overkill. You have to use the constructor that takes a TransactionOptions object and change the behavior to ReadCommitted. A second gotcha with TransactionScope is that you have to be very careful how you manage connections: if you open more than one connection under a scope then they will be enrolled in a distributed transaction, which is slow and requires MSDTC to be configured, and leads to all sort of hard to debug errors. But overall I fell that the benefits of using TransactionScope outweight the problems, and the resulted code is always more elegant than passing around IDbTransaction explicitly.

于 2011-06-09T16:54:15.460 に答える