Mono.Data.Sqlite抛出exception

我在我的应用程序中使用SQLite作为数据库引擎,但同时应用程序必须是跨平台的,所以我决定使用Mono.Data.Sqlite。 这就是我所做的:

  • 安装了最新版本的Mono(4.0.2 SR 2),将Mono的目录(net4_5)中的Mono.Data.Sqlite.dll复制到我在Visual Studio 2015中的项目

  • 下载并复制预编译的sqlite3.dll库。

然后我写了一个简单的应用程序:

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(); } 

但我面临一些问题:

  • 首先,当我在连接字符串中使用Data Source = file:{0}时,它会抛出一个exception:“不支持URI格式”。 将其替换为URI = file:{0}会有所帮助,但为什么第一个选项不起作用?

  • 其次,当我调用conn.ChangePassword(“testpassword”)时,它会抛出exception:System.EntryPointNotFoundException:无法在DLL“sqlite3”中找到名为“sqlite3_rekey”的入口点

  • 第三,使用URI = file:{0}; Password = testpassword与已加密的数据库抛出exception:System.EntryPointNotFoundException:无法在DLL“sqlite3”中找到名为“sqlite3_key”的入口点

它实际上不会发生在SQLite的官方包装器上,而是发生在Mono的。

当我不使用加密和数据源=文件时,PS Mono的包装器正常工作:{0}而不是URI = file:{0}

PSS Windows 10,Visual Studio 2015 +最新版Mono和SQLite

对于第一个问题,将URI转换为本地文件路径; new Uri(databaseFileURI).LocalPathfile://file:不被Sqlite使用并被C#帮助程序代码剥离,请参阅“Mono.Data.Sqlite_2.0 / SQLiteConnection.cs”中的代码。

对于第二/第三个问题:

您拥有的sqlite3本机库似乎与Mono的dll import语句不匹配,您可以使用bindump /EXPORTS来确认这一点。 Mono DllImports和匹配的SQLite .h导出如下:

注意:这当然假设您具有本机dll的正确ARCH,并且您没有在Windows中编译Uni-app。

Grep’ing出“Mono.Data.Sqlite_2.0 / UnsafeNativeMethods.cs”的来源

其次,当我调用conn.ChangePassword(“testpassword”)时,它会抛出exception:System.EntryPointNotFoundException:无法在DLL“sqlite3”中找到名为“sqlite3_rekey”的入口点

 #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); 

第三,使用URI = file:{0}; Password = testpassword与已加密的数据库抛出exception:System.EntryPointNotFoundException:无法在DLL“sqlite3”中找到名为“sqlite3_key”的入口点

 #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); 

匹配的sqlite.h定义:

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