maque
maque

Reputation: 23

Mono.Data.Sqlite throws exceptions

I'm using SQLite as database engine in my app, but at the same time the application must be cross-platform, so i have decided to use Mono.Data.Sqlite. And this what i did:

And then i wrote a simple app:

        const string databaseFileName = "somedata.db";
        var path = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + databaseFileName;

        if (!File.Exists(path)) SqliteConnection.CreateFile(databaseFileName);

        var connString = string.Format("Data Source=file:{0}", databaseFileName);

        using (var conn = new SqliteConnection(connString))
        {
            conn.Open();

            /* Some code */
            conn.ChangePassword("testpassword");
            conn.Close();
        }

But i'm facing with some issues:

It doesn't actually happen with official wrapper for SQLite, but happens with Mono's.

P.S. Mono's wrapper works normally when i don't use encryption and Data Source=file:{0} instead of URI=file:{0}

P.S.S. Windows 10, Visual Studio 2015 + latest version of Mono and SQLite

Upvotes: 0

Views: 1910

Answers (1)

SushiHangover
SushiHangover

Reputation: 74209

For the first issue, convert your URI to a local file path; new Uri(databaseFileURI).LocalPath. The file:// or file: is not used by Sqlite and stripped by the C# helper code, see the code in "Mono.Data.Sqlite_2.0/SQLiteConnection.cs".

For the second/third issues:

The sqlite3 native lib that you have appears to not match the Mono's dll import statements, you can use bindump /EXPORTS to confirm this. The Mono DllImports and the matching SQLite .h exports follows:

NOTE: This of course assumes you are have the correct ARCH for the native dll and you are not compiling a Uni-app in Windows.

Grep'ing out the source of "Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs"

Second, when i call conn.ChangePassword("testpassword") it throws an exception: System.EntryPointNotFoundException: Unable to find an entry point named "sqlite3_rekey" in DLL "sqlite3"

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_key(IntPtr db, byte[] key, int keylen);

Third, using URI=file:{0};Password=testpassword with the already encrypted database throws an exception: System.EntryPointNotFoundException: Unable to find an entry point named "sqlite3_key" in DLL "sqlite3"

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_rekey(IntPtr db, byte[] key, int keylen);

The matching sqlite.h defines:

...
SQLITE_API int SQLITE_STDCALL sqlite3_rekey
...
SQLITE_API int SQLITE_STDCALL sqlite3_key
...

Upvotes: 0

Related Questions