【发布时间】:2014-06-26 15:14:12
【问题描述】:
使用 64 位程序时 System.Data.SQLite 抛出以下 EntryPointNotFoundException:
无法在 DLL“SQLite.Interop.dll”中找到名为“sqlite3_changes_interop”的入口点。
奇怪的是,只有在连接字符串中指定了Foreign Keys=True,更重要的是,只有在我显示FolderBrowserDialog 之后才会出现这种情况。我正在浏览一个文件夹来显示要加载的数据库。
以下代码显示问题:
public Form1()
{
InitializeComponent();
// Exception below if this is displayed
using (var diag = new FolderBrowserDialog())
{
diag.ShowDialog(this);
}
var conn = new SQLiteConnection("data source=':memory:'");
conn.Open(); // Works fine
conn.Close();
// No exception below if displayed here instead
//using (var diag = new FolderBrowserDialog())
//{
// diag.ShowDialog(this);
//}
conn = new SQLiteConnection("data source=':memory:';foreign keys=True");
conn.Open(); // EntryPointNotFoundException thrown here
conn.Close();
}
如果对话框未显示或在打开任何其他 SQLite 连接后显示,则使用 foreign keys=True 打开连接可以正常工作。如果程序作为 32 位进程运行,该代码也可以正常工作。如果我使用单一混合模式 x64 SQLite 程序集或 MSIL + x64 互操作程序集,则行为也是相同的。我使用的是 v1.0.92.0,所以this 不是问题。
所以问题是为什么显示FolderBrowserDialog 会影响 System.Data.SQLite 程序集在其自己的互操作库中查找入口点,为什么它只会出现在 64 位进程中?
作为一种解决方法,我可以在程序中执行任何其他操作之前加载内存数据库,但我不喜欢这种“解决方案”,因为我使用的是 EF6,并且希望能够使用通过配置的不同提供程序配置文件,甚至在运行时通过用户输入。因此,所有的 sqlite 特定代码都在另一个程序集中。
【问题讨论】:
-
在 64 位系统上加载
FolderBrowserDialog将初始化 64 位编组,从而为 32 位本机代码带来问题。在这种情况下,对本机 DLL 使用 64 位 SQlite 构建。 -
@EugenRieck SQLite.Interop.dll 和混合模式 System.Data.SQLite.dll 是 64 位版本。使用溢出(MSIL + 互操作)或单一混合模式程序集对行为没有影响。
-
我说的不是 .NET 程序集,而是这些调用的本机 DLL。
-
@EugenRieck 本机 dll 包含在混合模式程序集中并且是 64 位的。
-
你确定吗?那么它怎么能作为 32 位进程运行呢?如果您的意思是托管和 32 位和 64 位本机混合模式,我一直看到这种方法失败。
标签: c# .net sqlite 64-bit system.data.sqlite