显示 FolderBrowserDialog 后 SQLite 中的 EntryPointNotFoundException [英] EntryPointNotFoundException in SQLite after displaying FolderBrowserDialog

查看:23
本文介绍了显示 FolderBrowserDialog 后 SQLite 中的 EntryPointNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用 64 位程序 System.Data.SQLite 时抛出以下 EntryPointNotFoundException:

When using a 64-bit program System.Data.SQLite is throwing the following EntryPointNotFoundException:

无法在 DLLSQLite.Interop.dll"中找到名为sqlite3_changes_interop"的入口点.

Unable to find an entry point named 'sqlite3_changes_interop' in DLL 'SQLite.Interop.dll'.

奇怪的是,只有在连接字符串中指定了 Foreign Keys=True 时才会发生,更重要的是只有在我显示 FolderBrowserDialog 后才会发生.我正在浏览一个文件夹以显示要加载的数据库.

Strangely it only occurs if Foreign Keys=True is specified in the connection string and more importantly only after I display a FolderBrowserDialog. I was browsing for a folder to display databases to load.

以下代码显示问题:

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 所以不是问题.

Opening the connection with foreign keys=True works fine if the dialog isn't shown or if it is shown after any other SQLite connection is opened. The code also works fine if the program runs as a 32-bit process. The behaviour is also the same if I use either the single mixed mode x64 SQLite assembly or the MSIL + x64 interop assembly. I'm using v1.0.92.0 so this is not the problem.

所以问题是为什么显示 FolderBrowserDialog 会影响 System.Data.SQLite 程序集在它自己的互操作库中找到入口点,为什么它只会出现在 64 位进程中?

So the question is why would showing the FolderBrowserDialog affect the System.Data.SQLite assembly finding the entry point in its own interop library and why would it only occur in a 64-bit process?

作为一种解决方法,我可以在程序中执行任何其他操作之前加载内存数据库,但我不喜欢这种解决方案",因为我使用的是 EF6,并且希望能够使用通过以下方式配置的不同提供程序一个配置文件,甚至在运行时通过用户输入.因此,所有特定于 sqlite 的代码都在另一个程序集中.

As a work around I can load an in-memory database before doing anything else in the program but I don't like this "solution" as I'm using EF6 and would like to be able to use different providers configured via a config file or even at runtime via user input. Hence all the sqlite specific code is in another assembly.

推荐答案

显示 FolderBrowserDialog 时正在加载旧版本的 System.Data.SQLite.如果计算机上安装了任何外壳程序/资源管理器扩展,则显示任何包含资源管理器的通用对话框将导致这些扩展中的程序集加载到应用程序的 AppDomain 中.

An older version of System.Data.SQLite is being loaded when displaying the FolderBrowserDialog. If there are any shell / explorer extensions installed on the computer then displaying any of the common dialogs which includes Explorer will cause assemblies from those extensions to be loaded into the application's AppDomain.

System.Data.SQLite 的情况下,本地库被加载 (SQLite.Interop.dll) 导致所有加载的程序集版本都使用该版本的本地图书馆.首先加载新版本的程序集会导致加载新版本的本机库.这仍然会导致在 AppDomain 中加载多个版本的程序集,这意味着 shell 扩展将使用与他们预期不同的版本.

In the case of System.Data.SQLite a native library is loaded (SQLite.Interop.dll) resulting in all loaded versions of the assembly to use that version of the native library. Loading the new version of the assembly first causes the new version of the native library to be loaded. This still results in multiple versions of the assembly being loaded in the AppDomain though and it means that shell extensions will be using a different version than they expect.

我尝试在不同的 AppDomain 中打开 FolderBrowserDialog,但它仍然导致程序集被加载到应用程序的正常 AppDomain 中.我在 Microsoft 连接 关于此问题,但我不太希望它会得到修复.

I tried opening the the FolderBrowserDialog in a different AppDomain but it still results in assemblies being loaded into the application's normal AppDomain. I've opened a bug on Microsoft connect regarding this but I'm not too hopeful that it will be fixed.

作为一种解决方法,我已将此添加到我的 app.config 中:

As a workaround I've added this to my app.config:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="System.Data.SQLite"
                        version="1.0.92.0"
                        publicKeyToken="DB937BC2D44FF139"
                        language="neutral"
                        processorArchitecture="msil" />
      <bindingRedirect oldVersion="0.0.0.0-1.0.91.65535" newVersion="1.0.92.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

这会导致仅加载 System.Data.SQLite 的单一版本.这仍然意味着 shell 扩展将使用错误的版本,因此可能会引发异常.

This results in only the single version of System.Data.SQLite being loaded. It does still mean that shell extensions will be using the wrong version and hence could potentially throw exceptions.

这篇关于显示 FolderBrowserDialog 后 SQLite 中的 EntryPointNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆