|
247b さん お手数かけます
わかり難い書込みのなか、回答ありがとうございます
10000文字超えのため、2度に分けました
>>DT.MDBがサーバー配置になるなら、確かにリンクテーブルの使用は微妙なラインです
詳細な説明ありがとうございます
勉強になります
Q1-1
添削頂きありがとうございます
サンプルコードが完全には理解出来ていないため
ldbが残りそうなところに
Set rst = Nothing
Set dbs = Nothing
を設けました
>レコードセットとデータベースを片付ける場合は、If not rst Is Nothing Then
>でオブジェクトが入っていることを確認した上で、Closeを呼び出した方が無難です。
了解です
上記
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
に置き換えました
>ここに Resumeがあると、どんなエラーが発生しても実行再開してしまいますが、
>それで問題ないですか?
了解です
ありがとうございました
VBA の Recordset オブジェクトで共有データをロックする
tp://msdn.microsoft.com/ja-jp/library/cc376533.aspx
に
エラーのチェック
なんてありましたが、なかなか難しいです
>他者のロックで開けなかった場合、ここに来るはずなので、
>ユーザーに再度実行を促し、一旦処理終了する。
>何回かリトライする
>のいづれかの対処ができると思います。
これなんですが
下記コードに記載しましたが
'ここは、
'dbs Is Nothing の時 ・・・・では?
と思いますが・・・
のでここには排他エラーが無いような気がしますが違っていますか?
(手動で開いて編集中、また、
別APP.MDBでSet DAOOpenTableExclusive = rst 中 共、どちらも同じで
'↓ココでエラーで止まる!!
Set rst = dbs.OpenRecordset(strRstSource, _
dbOpenTable, dbDenyRead + dbDenyWrite)
となってしまいました
但し、どちらも先行命令が完了すれば、後攻命令も問題なく完了します)
>排他制御も最終的には、業務要件によってどれだけシビアなものが要求されるかが決まります。
勉強になります
ありがとうございます
>その意味では、現在作っている処理を様々なパターンでテストしてみてはいかがでしょうか。
この辺の対応どのようにして作りこむのか良くわかりません・・・難しいです・・
配布後、苦情の嵐とかに遭遇しそうな・・・・
で
DAOのロック系のエラーを調べてみたのですが
どのエラーが
>他者のロックで開けなかった場合、ここに来るはずなので、
となるのかわからなかったので
DAOのエラー定数一覧
tp://homepage2.nifty.com/Dee/vb/tips/daoerrorlist.html
(MSサイトでは見つけられませんでした)
エラー番号 エラーメッセージ
3006 データベース <データベース名> は排他ロックされています。
3008 テーブル <テーブル名> は排他ロックされています。
3009 テーブル <テーブル名> は現在使用されているため、ロックできませんでした。
3046 他のユーザーによってロックされているため、保存できませんでした。
3158 他のユーザーによってロックされているため、レコードは保存できませんでした。
3186 マシン <マシン名> のユーザー <ユーザー名> によってロックされているため、保存できませんでした。
3187 マシン <マシン名> のユーザー <ユーザー名> によってロックされているため、読み取れませんでした。
3188 このマシンの他のセッションによってロックされているため、更新できませんでした。
3189 テーブル <テーブル名> は、マシン <マシン名> のユーザー <ユーザー名> によって排他ロックされています。
3202 他のユーザーによってロックされているため、保存できませんでした。
3211 テーブル <テーブル名> は現在使用されているため、ロックできませんでした。
3212 テーブル <テーブル名> は、マシン <マシン名> のユーザー <ユーザー名> によって使用されているため、ロックできませんでした。
3218 ロックされているため、更新できませんでした。
3260 マシン <マシン名> のユーザー <ユーザー名> によってロックされているため、更新できませんでした。
3261 テーブル <テーブル名> は、マシン <マシン名> のユーザー <ユーザー名> によって排他ロックされています。
3262 テーブル <テーブル名> は、マシン <マシン名> のユーザー <ユーザー名> によって使用されているため、ロックできませんでした。
をエラー処理の対象にしてしまえばいいかなと組み込んでしまいました・・・
邪道みたいな気もするのですが・・・・
遭遇するエラーは何とか処理の記載は出来る気もするのですが・・・
未遭遇のもの、特に今回の場合??です
というわけでこんなハズカシコードになってしまいました (~_~;)
何かアドバイス有りましたらよろしくお願い致します
修正コード
Function DAOOpenTableExclusive(strDBPath As String, _
strRstSource As String) As DAO.Recordset
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim cnt As Integer '登録チャレンジ回数
cnt = 0
On Error GoTo ErrorHandler
' DAOOpenDBShared を呼び出して
' データベースを共有モードで開きます。
Set dbs = DAOOpenDBShared(strDBPath)
' データベースが共有モードで開いたことを確認します。
' 開いた場合、指定したテーブルを排他的に開きます。
If Not dbs Is Nothing Then
'strRstSourceが開かれていると
'実行時エラー '3262': テーブル 'DT02_PJ_DT' は、マシン 'K000040827' のユーザー 'Admin' によって使用されているので、ロックできませんでした。
'で停止してしまう
'DAOOpenTableExclusive2で、エラー処理組み込みテスト
'↓ココでエラーで止まる!!
Set rst = dbs.OpenRecordset(strRstSource, _
dbOpenTable, dbDenyRead + dbDenyWrite)
' レコードセットが開いたことを確認します。開いた場合、
' Recordset オブジェクトを返します。開かなかった場合、Nothing を返します。
If Not rst Is Nothing Then
Set DAOOpenTableExclusive = rst 'レコードセット ロックで開いている
'追加しないと ldb.MDBが残る
'更新処理!!
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
MsgBox "登録完了"
Else
Set DAOOpenTableExclusive = Nothing
'ldbが残るとやなので、下記Nothingしています!!!!!
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
End If
Else
'他者のロックで開けなかった場合、ここに来るはずなので、
'ユーザーに再度実行を促し、一旦処理終了する。
'何回かリトライする
'のいづれかの対処ができると思います。
’ここは、
’dbs Is Nothing の時 ・・・・
'Set OpenTableExclusive = Nothing
Set DAOOpenTableExclusive = Nothing
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
End If
Exit Function
ErrorHandler:
'If Err.Number = 3262 Then
Select Case Err.Number
Case 3006, 3008, 3009, 3046, 3158, 3186, 3187, 3188, 3189, 3202, 3211, 3212, 3218, 3260, 3261, 3262
'MsgBox "エラーです"
'MsgBox "ターゲットテーブルは排他ONで使用中です"
'MsgBox Err.Description 'テーブル 'DT02_PJ_DT' は、マシン 'K000040827' のユーザー 'Admin' によって使用されているので、ロックできませんでした。
'動作良好そう
'ループかタイマで待機 駄目なら 時間を置いて と 思うが 動作的に 複数台のPCが ココでバッティングしたらどうなるのか自信がない
'排他で開いていたら3回チャレンジして中止
If cnt = 4 Then
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'レコードセットとデータベースを片付ける場合は、If not rst Is Nothing Then
'でオブジェクトが入っていることを確認した上で、Closeを呼び出した方が無難です。
'----------------------------------------------------
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
MsgBox "ファイルが使用中か不具合が発生している可能性があります 時間を置いて登録できないときは管理者に連絡してください"
Exit Function
End If
cnt = cnt + 1
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'Resumeはここにあるべきでは?
'----------------------------------------------------
Resume
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'Else
Case Else
MsgBox "エラー " & Err.Number & "" & Err.Description & " が発生しました"
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
dbs.Close
Set dbs = Nothing
Exit Function
'End If
End Select
'Resume
End Function
Function DAOOpenDBShared(strDBPath As String) As DAO.Database
' このプロシージャには、Micrsoft DAO 3.6 オブジェクト ライブラリへの参照が
' 必要です。このプロシージャは、データベースを共有モードで開けるかどうかを
' 調べます。開けない場合は Nothing を返します。
' レコードセット ロックをインプリメントする場合、このプロシージャで
' データベースを共有モードで開くことができます。
'
' 引数 :
' strDbPath : データベースへのパスです。
'
' 戻り値 :
' 共有モードで開かれているデータベースを参照する Database オブジェクトです。
Dim dbs As DAO.Database
On Error Resume Next
' データベースを開きます。
Set dbs = DAO.OpenDatabase(strDBPath, False)
' エラーを確認します。
If Err <> 0 Then
MsgBox "Cannot open database in shared mode. " & _
vbCr & Err.Description
' Nothing を返します。
Set DAOOpenDBShared = Nothing
Else
' データベースへの参照を返します。
Set DAOOpenDBShared = dbs
End If
End Function
今回は、取合えずテーブルロックで大丈夫そうな気がするのと
レコードレベルでの操作は荷が過ぎそうなので
テーブルロックで進めてみようと思います
|
|