VB.NET覚書 64bit AccessファイルODBC接続

客先で使うOfficeが64bitというので、普段は32bit版しか使っていない私は、トラブリューの渦に巻き込まれている。
VB.NET(Framework4.6/4.8)
ODBC接続(64bit)でAccessファイル(*.accdb)に接続
DB接続ライブラリはADODB(6.0)
 という環境を前提にしてメモ。

  1. ODBC接続(64bit)
  2. Office2019の64bit版をインストールしたにも関わらず、ODBCデータソース(64bit)の画面上にはAccess64bit用のODBC接続ドライバは表示されない。
    ネットで調べて何とか探し当てたのが
    Microsoft Access データベース エンジン 2016 再頒布可能コンポーネント
    日本語版でダウンロードしても英語版しか取得できない・・・というお粗末な状態だが、exeを実行することで、accdb形式のファイルに64bit接続ができるようになった。
    ちなみに、ADODBの2.8とかだと動かなかったので、ADODBは6.0に。

  3. VB.netでのコーディング
  4. 正直、Accessファイルじゃなかったら、64bitじゃなかったら、こんなに大変じゃないのかも・・・と思った。
    情報があまりにもない。(というか検索に引っかからないだけなのかもしれないし、検索の仕方がヘタなのかもしれないが、Accessはあっても64bitな情報じゃなかったりする。)

    • OPEN
    • Accessへの接続文字列は 「DSN=***;UID=;PWD=***;」
      DSNはODBC設定した名前。Accessなのでユーザ名は空。PWDはAccessを開くときのパスワードを設定。

      Dim conn As ADOBC.Connection = New ADOBC.Connection
      Dim ConnStr As String = "***"  '(接続文字列を設定)
      conn.ConnectionTimeout = **    '(タイムアウト秒数)
      conn.CursorLocation = ADODB.CursorLocationEnum.adUseClient  '!!!ココめっちゃ重要
      conn.Open(ConnStr)
      

      特に重要なのは、CursorLocationの設定。
      これが「adUseServer」になっていると、トランザクションの開始ができない。
      そもそもDocsを見ると初期設定はadUseClientであると書いてあるのだが、なぜadUseServerになるのだろうか。
      (ODBC設定をするときにシステムDSNでなくユーザーDSNに設定していたらいいのかな、とも思うのだが、複数ユーザで利用されることも考えてシステムDSNの設定は続行。詳細は不明。)
      【参考URL】
      Programer to Programer「Error – Attribute cannot be set now」
      トランザクション開始時に「Attribute cannot set now」のエラーが出た時にネットを探しまくったら出てきた英語のページ。
      このページの最後ぐらいに、

      This is because the RecordSet is already open. That is why we cannot participate in Begin Transaction. To overcome this problem we have to open RecordSet with the CursorLoction property as adUseClient.
      Ex .. RS.CursorLocation = adUseClient

      とあるので、試したところトランザクションが開始できるようになった。

    • CLOSE
    • 切断処理も厄介だった。閉じてもlaccdbファイルが残ってるし!!!!
      ってなって、切断直後、すぐに同じAccessファイルと接続しようとしたらエラーになってしまう現象が発生。
      これもネットで調べて、なんとなく解決させた。

      System.Runtime.InteropServices.Marshal.ReleaseComObject(conn)
      

      解放文の前に
      conn IsNot Nothing とか、System.Runtime.InteropServices.Marshal.IsComObject(conn)
      のIF文をつけておくと確実。

      laccdbのファイルを削除すればいいじゃん!みたいな記事も見たのだが、Killしてもファイル削除できなかったし、Closeしてからガベージコレクションを実行させたら何とかなるんじゃないかと思ってやってみたものの、これもダメだった。

    • 最適化
    • これはADOでなく、DAO3.6を使う。

      Dim dbe As Dao.Engine = New Dao.Engine
      dbe.CompactDatabase("元ファイル","保存ファイル",";pwd=***",Dao.DatabaseTypeEnum.dbVersion120, ";pwd=***")
      

      最適化は最適化したファイルを別名保存することになるので、最適化が済んだら、元ファイルを削除して保存ファイルをRenameする処理が後続処理として発生する。
      ここで重要なのは引数の「Dao.DatabaseTypeEnum.dbVersion120」
      Officeのバージョンによって異なるのだが、2019なのでdbVersion120にしている。
      この引数を設定していなかったときは、処理が動かなかったので、Optionな引数なくせに必須。
      パスワードがなければ、3つ目と5つ目の引数はなし。

Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください