Связь с 32-битным доступом из 64-битной .NET - PullRequest
0 голосов
/ 10 мая 2019

У меня есть приложение .NET (C #), которое должно быть скомпилировано 64 бит.При этом ADO.NET используется для работы с различными базами данных, включая Excel и Access с OLEDB (да, я знаю, Excel не нравится, когда с ним обращаются как с базой данных, но клиенты действительно хотят это делать, поэтому я разрешаю это с большим количеством предупреждений)

Все хорошо, пока мы не столкнемся с системой с 32-битным Office.64-разрядное приложение не может использовать 32-разрядные драйверы OLEDB.

Теперь 32-разрядное взаимодействие с Excel работает с использованием COM.Итак, я провел несколько тестов и могу написать альтернативный интерфейс для Excel, который использует Excel COM.

Итак, я также попробовал Access.Некоторые описания этого онлайн-намека на то, что DAO будет работать.Однако копать глубже это не похоже на правду.DAO сталкивается с теми же 32-битными / 64-битными проблемами.

Используя COM-интерфейс Access, я могу запросить список имен таблиц, но это все.Например,

  Access.Application accessApp = new Access.Application();
  accessApp.Visible = false;
  accessApp.OpenCurrentDatabase("mydb.accdb", false, "");

  Access._CurrentData dt = accessApp.CurrentData;
  foreach ( dynamic tbl in dt.AllTables )
  {
      string name = tbl.Name;
      if (! name.StartsWith("MSys"))
          Console.WriteLine(">" + tbl.Name+"< ");
  }
  accessApp.Quit();

Это предел того, что я могу сделать?Я хотел бы иметь возможность запрашивать столбцы таблицы и их типы.Запросить строки данных (достаточно было бы просто «извлечь все») и обновить строки (достаточно было бы ОБНОВЛЕНИЕ ГДЕ).

Мне не нужно поддерживать JET.

Как можноЯ читаю строки данных и обновляю их, используя Access COM-интерфейс без DAO или OLEDB, которые не будут взаимодействовать через 32-битную / 64-битную границу?

1 Ответ

1 голос
/ 11 мая 2019

К сожалению, вы не можете сделать это.

В то время как взаимодействие имеет мешок трюков и использует форму «маршаллинга», чтобы позволить запущенному x64 запустить + автоматизировать 32 битверсия word, или в данном случае Access, система взаимодействия взаимодействия не поддерживает механизм базы данных.

Итак, вот как вы могли бы кодировать вещи «если», это будет работать:

    Dim accessApp As New Access.Application
    accessApp.OpenCurrentDatabase("\\ALBERTKALLAL-PC\test\vbtest\test44.accdb")
    Dim strSQL As String
    accessApp.Visible = True
    Application.DoEvents()

    strSQL = "select * from tblHotels3"
    Dim rst As Access.Dao.Recordset

    Dim strBuf As String = ""
    rst = accessApp.CurrentDb.OpenRecordset(strSQL)
    Do While rst.EOF = False
        strBuf += vbCrLf & rst("ID").Value & "," & rst("HotelName").Value
        rst.MoveNext()
    Loop
    Me.TextBox1.Text = strBuf
    accessApp.Quit()

Итак, приведенный выше код - это то, как вы могли бы использовать взаимодействие, если это было возможно.

Однако имейте в виду, что вам требуется полная версия Access, чтобы использовать "createObject ()" или создать экземпляр Access,Версия во время выполнения не поддерживает это (поэтому просто имейте в виду, что, несмотря на то, что вы ДОСТИГЛИ успешное создание экземпляра Access, вы не можете делать это во время выполнения. (Теперь в вашем случае у вас, очевидно, установлена ​​полная версия доступа).).

И, создав ВЕСЬ экземпляр доступа, тогда весь код запуска и части этого приложения Access начнут работать. Гораздо лучше было бы просто создать экземпляр механизма базы данных, итаким образом, вы не запускаете Access + VBA + ВСЕ приложение. Чтобы использовать взаимодействие, этот код будет работать:

    Dim db As New Access.Dao.DBEngine
    Dim MyDatabase As Access.Dao.Database

    db.OpenDatabase("\\ALBERTKALLAL-PC\test\vbtest\test44.accdb")
    Dim rst As Access.Dao.Recordset
    Dim strSQL As String = "select * from tblHotels3"
    Dim strBuf As String = ""
    rst = db.Workspaces(0)(0).OpenRecordset(strSQL)
    Do While rst.EOF = False
        strBuf += vbCrLf & rst("ID").Value & "," & rst("HotelName").Value
        rst.MoveNext()
    Loop
    rst.Close()
    db.Workspaces(0)(0).Close() 
    Me.TextBox1.Text = strBuf

Еще раз, однако, в тот момент, когда вы попытаетесь использовать механизм данных, локальный для .net, затем вы выполняете маршалинг по всему процессу (x64), и, таким образом, снова вышеприведенное не будет работать.

Однако, если вы хотите изменить текстовый файл, вы можете иметь слово, открывающее текстовый документ,выполнить команды word, чтобы изменить документ и сохранить его. Теоретически это будет работать над мостом x32 / x64.

Фактическиследующий код для Access inter-op ДОЛЖЕН работать, но он не работает:

    Dim accessApp As New Access.Application
    accessApp.OpenCurrentDatabase("\\ALBERTKALLAL-PC\test\vbtest\test44.accdb")

    Dim strSQL As String

    strSQL = "update tblHotels3 set City = 'zoo' "

    accessApp.DoCmd.RunSQL(strSQL)
    accessApp.Quit()

Обратите внимание, что мы пытаемся использовать модель Access для "обновления".Тем не менее, мгновенный доступ пытается запустить + использовать ядро ​​базы данных, это не удается.Приведенный выше пример ДОЛЖЕН работать, но если приведенный выше код .net (vb.net) выполняется как x64, найдите:

Код действительно создает работающий экземпляр Access (.net = x64, Access= x32).

Тем не менее, кажется, что в тот момент, когда мы пытаемся попробовать запустить + использовать механизм доступа к данным, затем .net выводит сообщение об ошибке (так что выше происходит сбой на accessApp.DoCmd.RunSQL (strSQL).) - вот когда мы пытаемся использовать механизм обработки данных).

Таким образом, несмотря на то, что взаимодействие может запустить + получить работающую копию Access, попытки использовать механизм обработки данных завершаются неудачей.

Я нахожу, что вы МОЖЕТЕ сказать MSAccess запустить некоторый код VBA.Так что это будет работать:

    Dim accessApp As New Access.Application
    accessApp.OpenCurrentDatabase("\\ALBERTKALLAL-PC\test\vbtest\test44.accdb")

    accessApp.Visible = True
    Application.DoEvents()
    MsgBox("access open = ok - show access ok")
    accessApp.Run("MyUpdate")
    accessApp.Quit()

И код VBA для выше?

Код VBA - не vb.net:

  Public Sub MyUpdate()

     MsgBox "about to update"
     CurrentDb.Execute "update tblHotels3 set city = 'zoozoo'"

     MsgBox "upate ok"


  End Sub

Я могу подтвердить, чтовыше работает:

Итак, проблема здесь в том, что ядро ​​базы данных Access рассматривается и рассматривается как объект внешней базы данных, а межоперационная сортировка не поддерживает ядро ​​базы данных из .net.

Единственный способ обойти это - установить 64-битную версию ядра данных Access.Вы можете установить движок отдельно и НЕ ДОЛЖНЫ устанавливать Access, но, насколько мне известно, из .net вы не сможете этого сделать, если у вас нет 64-битной версии движка данных.

...