|
▼pon さん:
>遅くなりました
>247b さん ありがとうございます
>
>
>>DT.MDBがサーバー配置になるなら、確かにリンクテーブルの使用は微妙なラインです。
>なんですが
>>>非連結にしましたが、
>>>結局、フォームを開くとき、
>>>コントロールのレコードソースを設定しているのでリンクテーブル有り同じことに
>>>なっているのではと思っています
>やはり、上記のような理解になってしまうのですが
>別途何か注意事項等あればコメント頂けるとうれしいです
>よろしくお願いいたします
経験的(感覚的には)リンクテーブルの方が動作は遅いような気がします。
注意事項としては、Access2000時代の話なので大丈夫だと思いますが、レコードソースプロパティを直接変更するタイプのプログラムを作って、MDBファイルがクラッシュした経験があります。事象としては、実体は数件しかデータが無いのに、数百万件データがあると認識されてしまうというものです。
こうなると、そのMDBファイルは使い物になりません。
が、稀な事象のようなので、今後のこともあるので、念のための情報として挙げておきます。
>DT.MDBが編集中で無ければ問題は無く、テーブル排他で開けましたが
>DT.MDBの競合テーブルが編集中の場合(手動で開いて編集)
> Set rst = dbs.OpenRecordset(strRstSource, _
> dbOpenTable, dbDenyRead + dbDenyWrite)
>でとまってしまいました
>そこで下記のようにエラー処理を追加してみました
>
>Call DAOOpenTableExclusive("\\hoge\DT.mdb","テーブル名")
>で実行
>
>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
> '※追記1
> 'strRstSourceが開かれていると
> '実行時エラー '3262': テーブル 'DT' は、マシン 'huga' のユーザー 'Admin' によって使用されているので、ロックできませんでした。
> 'で停止してしまう
> '↓ココでエラーで止まる!!
> Set rst = dbs.OpenRecordset(strRstSource, _
> dbOpenTable, dbDenyRead + dbDenyWrite)
> ' レコードセットが開いたことを確認します。開いた場合、
> ' Recordset オブジェクトを返します。開かなかった場合、Nothing を返します。
> If Not rst Is Nothing Then
> Set DAOOpenTableExclusive = rst 'レコードセット ロックで開いている
> ※追記2
> '追加しないと ldb.MDBが残る
Nothingにする前に念のためCloseしてください。
> Set rst = Nothing
> Set dbs = Nothing
>
> Else
>
> Set DAOOpenTableExclusive = Nothing
> Set rst = Nothing
> Set dbs = Nothing
> End If
> Else
> 'Set OpenTableExclusive = Nothing
> Set DAOOpenTableExclusive = Nothing
> Set rst = Nothing
> Set dbs = Nothing
他者のロックで開けなかった場合、ここに来るはずなので、
ユーザーに再度実行を促し、一旦処理終了する。
何回かリトライする
のいづれかの対処ができると思います。
> End If
>
>
>Exit Function
>
>ErrorHandler:
> If Err.Number = 3262 Then
> 'MsgBox "エラーです"
> 'MsgBox "ターゲットテーブルは排他ONで使用中です"
> 'MsgBox Err.Description 'テーブル 'DT' は、マシン 'hoge' のユーザー 'Admin' によって使用されているので、ロックできませんでした。
> '動作良好そう
> 'ループかタイマで待機 駄目なら 時間を置いて と 思うが 動作的に 複数台のPCが ココでバッティングしたらどうなるのか自信がない
> '排他で開いていたら3回チャレンジして中止
> If cnt = 4 Then
> Set rst = Nothing
> Set dbs = Nothing
レコードセットとデータベースを片付ける場合は、If not rst Is Nothing Then
でオブジェクトが入っていることを確認した上で、Closeを呼び出した方が無難です。
> MsgBox "ファイルが使用中か不具合が発生している可能性があります 時間を置いて登録できないときは管理者に連絡してください"
> Exit Function
> End If
> cnt = cnt + 1
Resumeはここにあるべきでは?
> Else
> MsgBox "エラー " & Err.Number & " _ " & Err.Description & " が発生しました"
> Set rst = Nothing
> Set dbs = Nothing
> Exit Function
> End If
> Resume
ここに 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
>
>Q1-1
>上記で一応動作するのですが、エラー処理等自信がありません
>添削、アドバイス等頂けるとうれしいです
インラインで追記しました。
>
>Q1-2
>下記レコード レベル ロックまたはページ レベル ロックの動作が理解しきれていないので
>場合によってはこのコードでもいけそうな気がしています
>多分、更新作業も瞬時だろうし、テーブル排他のため、データの競合も発生しないので
>よさげな気がしますが、APP.MDBからのフォームの参照が切れてしまうような気がしますが
>まだ試していません
>この辺、駄目とかいけそうとかアドバイス頂けると助かります
>よろしくお願いいたします
排他制御も最終的には、業務要件によってどれだけシビアなものが要求されるかが決まります。
業務上、更新作業がほとんど重ならない程度の頻度であれば、プログラムを作り込みすぎても
重武装になるだけでメンテナンスが大変になります。
レコードのロック制御
ロックの解除制御
他人にロックされた場合の対処方法(リトライするとか、メッセージを表示するとか。処理終了するタイミングなど)
が明確になっていて、且つ実装されていれば大丈夫ではないでしょうか。
その意味では、現在作っている処理を様々なパターンでテストしてみてはいかがでしょうか。
動いているところを見ていないので、なんとも言えない部分もあるのですが。
>
>レコード レベル ロックまたはページ レベル ロック UpdateUnitsInStock
>についてですが
>
>アクセス付録のNwind.mdbをコピーして使用
>サンプルコード内でNwind.mdbフルパス、テーブル名指定
>
>Function UpdateUnitsInStock(strProduct As String, _
> intUnitsInStock As Integer, _
> intMaxTries As Integer) As Boolean
>は
>strProduct は Product Name 列で 商品選択
>Units In Stock は 更新DT値
>intMaxTries は 回数 指定
>CALL UpdateUnitsInStock("Chang","33","5")
>で実行
>
>Q2-1
>うまく intMaxTries の動作を チェックすることが出来ません
>intMaxTries の デバッグ を するにはどうすればいいでしょうか
CALL UpdateUnitsInStock("Chang","33","5")
の行を選択して、「F9」キーを押し、ブレークポイントを置きます。(茶色になる)
プログラムを実行すると、このブレークポイントで処理が止まるので、あとは
ステップインして、「F8」でステップ実行で動きを確認できます。
ステップインは、ツールバーの「デバッグ」にボタンがあります。
あと、UpdateUnitsInStockの第2、3引数は数値型なので、ダブルクォーテーションは不要です。
>
>Q2-2
>別マシンでDT.MDBのProductsを開いていても
>上記を実行すると数秒、別マシンのレコードが自動更新されて再表示されます
>
>次に、別マシンでDT.MDBのProductsを開いて Units In Stock を 編集し
>上記を実行し、別レコードに移動すると
>データの競合 の ダイアログが表示され
>"レコードの保存"、"クリップボードにコピー"、または "他のユーザーによる変更を反映"
>のオプションが表示されます
>これは
>>><ADOを使ったレコード単位の排他ロックについて>
>>>tp://www5f.biglobe.ne.jp/~f-lap/tips_adolock.htm
>でも同じ動作になりした
>別マシン側ででDT.MDBのProducts で 処理選択するか
>レコード移動しなくてはいけない状況のように思われます
>
>イメージ的には、
>Function UpdateUnitsInStock
>の動作の中で、編集中です とか 待機、ループで自動処理
>できないものかと思っています
>要領を得ない質問のような気がしますが、アドバイス頂けるとうれしいです
>よろしくお願いいたします
この質問が状況が読めないのですが、レコードセットにRequeryをかけたらうまくいきませんか?
>
>Q3
>MDB破損の話はよく見かけるのですが
>今回のように、APP.MDB、DT.MDBを分離しても同じでしょうか
>壊れる、運用可 のいろんな書き込みがあってよく理解できていません
>実際にはどうなんでしょう?
>アドバイスよろしくお願いいたします
>(SQLサーバーについては、今後の目標にしています)
経験的な情報なので、確実ではないと思いますが、データベースの最適化を頻度高く行うと長持ちするように思います。このシステムの場合、特にDT.MDBの方が必要です。
また、残念ながら、MDBファイルは壊れるもの、という前提で運用する方が無難なので、バックアップ運用をすることが望ましいと思います。これも業務要件によるのですが、3〜5日分のバックアップを持っておけば、いざ壊れても復旧はしやすいはずです。
|
|