トップ回答者
BeginTransactionが破棄されるまでの数瞬の動きについて

質問
-
下記ソースにてご指摘ください。
環境:VS2015
MVC5 スキャフォールディング機能を利用 リポジトリ、インタフェースを実装
Using tx = _db.Database.BeginTransaction
Try
(DBへの処理 A)
_db.SaveChanges()
(DBへの処理 B)
_db.SaveChanges()
(DBへの処理 C)
_db.SaveChanges()
'コミット
Call tx.Commit()
Return True
Catch ex As Exception
'ロールバック
Call tx.Rollback()
Return False
End TryEnd Using
【【【 Aのテーブルからデータを取得】】】
ご教示いただきたいのは、Aのテーブルからデータを取得するのに、DBコンテキストを利用しているのですが
時々、Execution Timeout Expired. だとか
Object reference not set to an instance of an object. というメッセージが出て
値が正しく取得できていません。
よくよく調べてみると、End Usingの時点で、
インタフェースで実装している Inherits IDisposable より
リポジトリクラスで実装している下記の自動生成されたソースが動き、DBコンテキストを破棄しているみたいです
(違っていたらご指摘ください)
#Region "IDisposable Support"
Private disposedValue As Boolean ' 重複する呼び出しを検出するには' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: マネージ状態を破棄します (マネージ オブジェクト)。
End If' TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下の Finalize() をオーバーライドします。
' TODO: 大きなフィールドを null に設定します。
_db.Dispose()
_db = Nothing
End If
disposedValue = True
End Sub' TODO: 上の Dispose(disposing As Boolean) にアンマネージ リソースを解放するコードが含まれる場合にのみ Finalize() をオーバーライドします。
Protected Overrides Sub Finalize()
' このコードを変更しないでください。クリーンアップ コードを上の Dispose(disposing As Boolean) に記述します。
Dispose(False)
MyBase.Finalize()
End Sub' このコードは、破棄可能なパターンを正しく実装できるように Visual Basic によって追加されました。
Public Sub Dispose() Implements IDisposable.Dispose
' このコードを変更しないでください。クリーンアップ コードを上の Dispose(disposing As Boolean) に記述します。
Dispose(True)
' TODO: 上の Finalize() がオーバーライドされている場合は、次の行のコメントを解除してください。
GC.SuppressFinalize(Me)
End Sub#End Region
聞きたいのは、EndUsingで破棄がすぐされるのであれば、直後のAのテーブルから値の取得は出来ないと思うのですが、
これは、EndUsingによりDisposeされるまでの数瞬は破棄されておらず有効であったとか
そういうことなのでしょうか?
ご教示いただければ幸いです。
回答
-
聞きたいのは、EndUsingで破棄がすぐされるのであれば、直後のAのテーブルから値の取得は出来ないと思うのですが、これは、EndUsingによりDisposeされるまでの数瞬は破棄されておらず有効であったとかそういうことなのでしょうか?
まったくの見当違いです。
Call tx.Commit()が完了した時点で書き込みは完了し、ロック解除されます。Disposeによるコネクション破棄のタイミングとは無関係です。
挙げられたコードだけでは何が起きているかは不明確ですが、「Execution Timeout Expired.」に関してはあるトランザクションの実行に時間を要し、そのトランザクションの完了を待つ別のトランザクションがタイムアウトした可能性があります。
「Object reference not set to an instance of an object.」に関してはオブジェクトインスタンスがforループの途中で破棄される事があると同じく挙げられている範囲のコードでは何が起きているのか特定できません。…というようにとにかく情報が足りません。
- 回答としてマーク rururururu 2017年5月1日 4:30
すべての返信
-
聞きたいのは、EndUsingで破棄がすぐされるのであれば、直後のAのテーブルから値の取得は出来ないと思うのですが、これは、EndUsingによりDisposeされるまでの数瞬は破棄されておらず有効であったとかそういうことなのでしょうか?
まったくの見当違いです。
Call tx.Commit()が完了した時点で書き込みは完了し、ロック解除されます。Disposeによるコネクション破棄のタイミングとは無関係です。
挙げられたコードだけでは何が起きているかは不明確ですが、「Execution Timeout Expired.」に関してはあるトランザクションの実行に時間を要し、そのトランザクションの完了を待つ別のトランザクションがタイムアウトした可能性があります。
「Object reference not set to an instance of an object.」に関してはオブジェクトインスタンスがforループの途中で破棄される事があると同じく挙げられている範囲のコードでは何が起きているのか特定できません。…というようにとにかく情報が足りません。
- 回答としてマーク rururururu 2017年5月1日 4:30
-
質問者さんが立てた前のスレッド:
オブジェクトインスタンスがforループの途中で破棄される事がある
https://social.msdn.microsoft.com/Forums/ja-JP/3b656d73-9a3c-44e2-8381-03c3c160dba9/for?forum=vbgeneraljaで、
> コードの詳細内容が不明なので単なる想像ですが・・・
>> Catch ex As Exception
> Exception を catch しているので例外が発生してもなかったことになってしまうという
> ことが怪しそうな気がします。> ・・・中略・・・
> 最初に書きましたが単なる想像ですので、Exception をキャッチは今回の問題の原因とし
> てはハズレかもしれません。ただし、Exception をキャッチするのは止めた方がいいのは
> 確かなようですので、それが原因ではなくても直した方がよさそうです。と書いたのですが、そのことは考慮されているのでしょうか?
-
SurferOnWww様
前回に引き続き、貴重なお時間をいただきご回答ありがとうございます。
前回ご指摘いただいた後、すぐさまスルーを追加し、Exceptionを消したのですが、
今回の質問に反映されておりませんでした。
>>質問者さんのコードではロールバックするために Exception を catch しているようですが、ロールバックしたら即例外を再スローしたらどうなりますか?
エラー発生頻度が低く、まだ2回ぐらいしか見えていないのですが、エラー文言等は変わったようには見えませんでした。
ヒントをいただけているのに有用な事を言えず申し訳ございません。