显示FolderBrowserDialog后,SQLite中的EntryPointNotFoundException

kjb*_*tel 3 .net c# sqlite 64-bit system.data.sqlite

使用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();
}
Run Code Online (Sandbox Code Playgroud)

foreign keys=True如果未显示对话框,或者在打开任何其他SQLite连接后显示对话框,则打开连接可正常工作.如果程序作为32位进程运行,代码也可以正常工作.如果我使用单一混合模式x64 SQLite程序集或MSIL + x64互操作程序集,行为也是相同的.我正在使用v1.0.92.0所以不是问题.

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

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

kjb*_*tel 5

System.Data.SQLite显示时将加载旧版本FolderBrowserDialog.如果计算机上安装了任何shell/explorer扩展,则显示包含Explorer的任何常用对话框将导致来自这些扩展的程序集加载到应用程序中AppDomain.

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

我尝试FolderBrowserDialog在不同的AppDomain中打开它,但它仍然导致程序集被加载到应用程序的普通AppDomain中.我已经在微软连接上打开了一个关于此问题的错误,但我不太希望它会被修复.

作为一种解决方法,我已将其添加到我的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>
Run Code Online (Sandbox Code Playgroud)

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