问题描述
我在我的应用程序中使用 SQLite 作为数据库引擎,但同时应用程序必须是跨平台的,所以我决定使用 Mono.Data.Sqlite.这就是我所做的:
安装最新版本的 Mono (4.0.2 SR 2),将 Mono.Data.Sqlite.dll 从 Mono 的目录 (net4_5) 复制到我在 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);使用 (var conn = new SqliteConnection(connString)){conn.Open();/* 一些代码 */conn.ChangePassword("testpassword");conn.Close();}
但我面临一些问题:
首先,当我在连接字符串中使用 Data Source=file:{0} 时,会引发异常:不支持 URI 格式".将其替换为 URI=file:{0} 会有所帮助,但为什么第一个选项不起作用?
其次,当我调用 conn.ChangePassword("testpassword") 时会抛出异常:System.EntryPointNotFoundException: Unable to find an entry point named "sqlite3_rekey" in DLL "sqlite3"
第三,对已经加密的数据库使用URI=file:{0};Password=testpassword会抛出异常:System.EntryPointNotFoundException: Unable to find an entry point named "sqlite3_key"在 DLL sqlite3"中
SQLite 的官方包装器实际上不会发生这种情况,但 Mono 会发生这种情况.
附:当我不使用加密和 Data Source=file:{0} 而不是 URI=file:{0}
时,Mono 的包装器正常工作附言Windows 10、Visual Studio 2015 + 最新版本的 Mono 和 SQLite
对于第一个问题,将你的URI转换为本地文件路径;新的 Uri(databaseFileURI).LocalPath
.file://
或 file:
未被 Sqlite 使用并被 C# 帮助代码剥离,请参阅Mono.Data.Sqlite_2.0/SQLiteConnection.cs".
第二/第三期:
您拥有的 sqlite3 本机库似乎与 Mono 的 dll 导入语句不匹配,您可以使用 bindump/EXPORTS
来确认这一点.Mono DllImports 和匹配的 SQLite .h 导出如下:
注意:这当然假设您对本机 dll 具有正确的 ARCH,并且您没有在 Windows 中编译 Uni-app.
查找Mono.Data.Sqlite_2.0/UnsafeNativeMethods.cs"的来源
<块引用>其次,当我调用 conn.ChangePassword("testpassword") 时,它会抛出一个异常:System.EntryPointNotFoundException:找不到条目DLLsqlite3"中名为sqlite3_rekey"的点
#if !PLATFORM_COMPACTFRAMEWORK[DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]#别的[DllImport(SQLITE_DLL)]#万一内部静态外部 int sqlite3_key(IntPtr db, byte[] key, int keylen);
<块引用>
第三,使用 URI=file:{0};Password=testpassword 与已经加密数据库抛出异常:System.EntryPointNotFoundException:找不到入口点在 DLLsqlite3"中命名为sqlite3_key"
#if !PLATFORM_COMPACTFRAMEWORK[DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]#别的[DllImport(SQLITE_DLL)]#万一内部静态外部 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...
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:
Installed the latest version of Mono (4.0.2 SR 2), copied Mono.Data.Sqlite.dll from Mono's directory (net4_5) to my project in Visual Studio 2015
Downloaded and copied precompiled sqlite3.dll library.
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:
First, when i'm using Data Source=file:{0} in connection string, it throws an exception: "URI formats are not supported". Replacing it to URI=file:{0} helps, but why the first option doesn't work?
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"
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"
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
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
...
这篇关于Mono.Data.Sqlite 抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!