14

I am developing a program in VB.net, and using System.Data.SQLite Precompiled Binaries for .NET, However It is not working for x64 Architectures, and I am getting the classic culture problem and not loading correct file.

System.BadImageFormatException: 
Could not load file or assembly 'System.Data.SQLite, Version=1.0.65.0, Culture=neutral,
 PublicKeyToken=db937bc2d44ff139' or one of its dependencies. An attempt was made to load a program with an incorrect format.
File name: 'System.Data.SQLite,
 Version=1.0.65.0,
 Culture=neutral, 
 PublicKeyToken=db937bc2d44ff139'

Is there a way to use only one dll, maybe:

  1. Add some directives like #IFDEF (x86 include some part of code) or else x64 code
  2. Join dlls to make only one.
  3. Reference this dll in VB.net

Do you think is other better Idea, as I would like to make only one compilation, not one for x32 and other for x64.

For instance (32 bits):

Private Shared Sub OpenConection(ByRef Conn As SQLite.SQLiteConnection)
    Conn = New SQLite.SQLiteConnection("Data Source=" & System.Environment.CurrentDirectory & "\database.db")
    Conn.Open()
End Sub

Private Shared Sub CloseConection(ByRef Conn As SQLite.SQLiteConnection)
    Conn.Close()
    Conn.Dispose()
    Conn = Nothing
End Sub

Public Shared Function ReturnSelect(ByVal DataTAbleName As String, ByVal sQuery As String, ByVal sWhere As String) As Data.DataTable
    Dim lDT As New DataTable
    Dim lTA As New SQLite.SQLiteDataAdapter
    If DataTAbleName Is Nothing Then Return New DataTable(DataTAbleName)
    Try
        OpenConection(conexion)
        lTA = New SQLite.SQLiteDataAdapter("SELECT " & sQuery & " FROM  " & DataTAbleName & IIf(sWhere <> String.Empty, " WHERE ", "") & sWhere, conexion)
        lTA.Fill(lDT)
    Catch ex As Exception
        Throw ex
    Finally
        CloseConection(conexion)
        lTA.Dispose()
        lTA = Nothing
    End Try
    Return lDT
End Function

How to change that to work on 64 bit architecture? Maybe including both 32 and 64 dll's and in functions do something like

Try
    Instance = Me
    'Check If Homidom Run in 32 or 64 bits
    If IntPtr.Size = 8 Then _OsPlatForm = "64" Else _OsPlatForm = "32"
    'continue code

Catch ex As Exception
    ' ex.Message
End Try
edgarmtze
  • 24,683
  • 80
  • 235
  • 386

5 Answers5

25

There are various options for using SQLite from a .NET assembly. Your first step is to move to something newer than the ancient 1.0.65 version. Current versions can be downloaded from here: http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki or via the SQLite NuGet packages.

If you need to be able to run under both 32-bit and 64-bit, one option is to use the native library pre-loading option, where you distribute the native binaries in separate directories, so that it looks like this:

  • \App.exe (optional, managed-only application executable assembly)
  • \App.dll (optional, managed-only application library assembly)
  • \System.Data.SQLite.dll (required, managed-only core assembly)
  • \System.Data.SQLite.Linq.dll (optional, managed-only LINQ assembly)
  • \x86\SQLite.Interop.dll (required, x86 native interop assembly)
  • \x64\SQLite.Interop.dll (required, x64 native interop assembly)

Another option is to build two versions of your app, and in each version you reference the appropriate mixed-mode assembly. You'd then end up with two versions, but they're a bit simpler to deal with since you don't need the extra subdirectory and native *.Interop.dlls.

In these cases you'd need no code differences or optional compilation between 32-bit and 64-bit. Installing from the different NuGet packages will probably get you started most easily.

A final option is to go for the managed-only clone called C#-SQLite: https://code.google.com/p/csharp-sqlite/. It's a port of the SQLite engine to managed C#, so the whole thing runs as AnyCPU and the bitness is not an issue.

Tobia Zambon
  • 7,479
  • 3
  • 37
  • 69
Govert
  • 16,387
  • 4
  • 60
  • 70
6

I had the same problem few year ago and for me the best solution is:

  • download the latest version of the library
  • in your bin path put only the System.Data.SQLite.dll and eventually System.Data.SQLite.Linq.dll
  • put the x86 SQLite.Interop.dll library into c:\Windows\SysWOW64
  • put the x64 SQLite.Interop.dll library into c:\Windows\System32
  • compile your project as Any CPU referencing only System.Data.SQLite (the dll into your bin path)
  • enjoy

In this way the .NET framework will automatically load the correct (x86 vs x64) library during the runtime without registering anything in GAC or similar.

Hope this helps.

Tobia Zambon
  • 7,479
  • 3
  • 37
  • 69
  • 1
    Which System.Data.SQLite.dll should I add on bin folder, x32 or x64 available dlls? I downloaded both x32 and x64 and each version has System.Data.SQLite.dll and their size is different.... – edgarmtze Oct 03 '13 at 07:02
  • Mmm they should have the same size, which versions did you download? – Tobia Zambon Oct 03 '13 at 07:39
  • I downloaded .net 2 binaries, as my application can not use > .net 2. Am I doing somthing wrong? – edgarmtze Oct 03 '13 at 14:09
  • 2
    it is correct, the two libraries are identical, I've checked it with a file comparer, you have to download [this for x86](http://system.data.sqlite.org/downloads/1.0.88.0/sqlite-netFx20-binary-Win32-2005-1.0.88.0.zip) and [this for x64](http://system.data.sqlite.org/downloads/1.0.88.0/sqlite-netFx20-binary-x64-2005-1.0.88.0.zip) – Tobia Zambon Oct 04 '13 at 08:38
  • 10
    Why on earth is this the accepted answer? Throwing libraries in system folders, seriously? This will make it a nightmare to deploy. – Odys Jun 28 '15 at 13:39
  • 1
    I second what @Odys says-- this is not the way to do it. Dropping the libraries into the GAC will work, but only on your one machine. Your program will still be broken for anyone else who installs it. – Eric Dand Aug 18 '15 at 21:15
1

No there isn't one.

That's because these *.dlls are just wrappers for native c/c++ *.dll's. And a 32 bit, .NET application have to use the 32 bit c/c++ dll and a 64 bit, .NET application have to use the 64 bit c/c++ dll.

I haven't used vb.net for a long time, I'm not sure if you can configure the target platform like you can do in c#. If you can, you should do so and take the right interop dll. And you should decide if you need 32 bit or 64 bit.

user743414
  • 936
  • 10
  • 23
  • So Do I need to compile twice, one for 32 and other for 64? – edgarmtze Oct 01 '13 at 15:14
  • Yes, if you want to provide a 32 and 64 bit version. Because if you set you target to "any cpu" it will compiled to the target version (64 or 32 depends on the target windows). You have to set your target to x86 (32 bit) or to x64 (64 bit). – user743414 Oct 02 '13 at 05:55
1

The other answers here by @Govert and @TobiaZambon are the right way to go. But for anyone else reading, another option is to use the x86 version of the System.Data.Sqlite dll and only compile your application for x86 platform. i.e. don't compile to AnyCPU, which means when it runs on x64 machine windows will run it in 32-bit mode and it'll be able to load the 32-bit dll.

Whether this is useful will depend on your situation, but if you're building an app that's deployed to workstations it's quite a simple solution.

Rory
  • 40,559
  • 52
  • 175
  • 261
1

The state of art of the question can easily be solved using Nuget After install it, search SQLite like:

PM> Install-Package System.Data.SQLite 

I have done this using a brand new computer and VS, I needed SQLite and did this and everything worked fine.

edgarmtze
  • 24,683
  • 80
  • 235
  • 386