月: 2021年8月

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つ目の引数はなし。

そりゃ感染広がるでしょう

ここ何週間かで、数回飲食店で飲食をする機会があった。
飲食店にいると、マスクをつけずにしゃべってるヤツばっかり。
複数人でやってきて、食べながら会話って・・・

「マスク会食」って忘れましたか???

向かい合っている相手は家族かもしれませんが、飛沫は何mか拡散するんですよぉ~
ワクチン打ったからって、感染させないわけじゃないんですよぉ~~~

これじゃぁ、いつまで経っても酒なんか呑めないですね。

と思いながら、孤独のグルメ派な私は、一人で入って、一人で食って、イソイソ帰ってくる日々。
(というより、一緒に行く人がいないだけなのだが。)