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).LocalPath
。 file://
或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 ...