在32位和64位c#环境中使用System.Data.SQLite的选项

本文关键字:System Data SQLite 选项 32位 64位 环境 | 更新日期: 2023-09-27 18:07:07

我理解为什么System.Data.SQLite.dll在32位和64位构建中提供。所以我们不要纠结于此,继续前进。:)

因为它是这样做的,它似乎使纯c#开发更困难,有3个选择。

  1. 是只支持32位和强制管理汇编编译x86和处理在32或64运行位,当你使用64位时,就会失去优势环境。

  2. 是强制64位,只支持64位而丢失能够在32位上运行,但获得64位的所有优点。

  3. 是创建他们的程序集的两个版本编译x86并使用32位SQLite和另一个编译x64并使用64位SQLite。它防止使用"ANY"作为编译选项并且能够轻松地将单个构建部署到任一类型。它的从开发的角度来看,这并不像我们这么可怕将需要两个项目。只有官方的c#代码,而另一个只会使用"链接"到另一个中的代码。这仅用于编译目的。但我们还是不得不为部署管理两个输出

说了这么多,我只是想确认以上是唯一正确的选择。

如果有其他的选择,我忽略了请让我知道。具体来说,如果有办法获得一个可以编译成任意格式的c# DLL,这样它就可以根据运行位置利用32位或64位的优势,并且仍然使用System.Data.SQLite.dll。

在32位和64位c#环境中使用System.Data.SQLite的选项

这是对Springy76的回答的详细阐述。这样做:

public class AssemblyResolver
{
    public static void HandleUnresovledAssemblies()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += currentDomain_AssemblyResolve;
    }
    private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.Name == "System.Data.SQLite")
        {
            var path = Path.Combine(pathToWhereYourNativeFolderLives, "Native");
            if (IntPtr.Size == 8) // or for .NET4 use Environment.Is64BitProcess
            {
                path = Path.Combine(path, "64");
            }
            else
            {
                path = Path.Combine(path, "32");
            }
            path = Path.Combine(path, "System.Data.SQLite.DLL");
            Assembly assembly = Assembly.LoadFrom(path);
            return assembly;
        }
        return null;
    }
}

确保生成的路径指向32位或64位SQLite dll的正确位置。就我个人而言,我在这个NuGet包中获得了很好的结果:http://www.nuget.org/packages/SQLitex64

(您只需要使用NuGet包来获取编译的SQLite dll。一旦你得到了它们,删除对NuGet和NuGet包本身创建的项目中的SQLite的引用。实际上,保留引用可能会干扰此解决方案,因为SQLite永远不会被识别为未解析的程序集。

尽早调用'HandleUnresolvedAssemblies()',最好是在任何Bootstrapping期间。

有两种常见的解决方案来保持您的主应用程序在AnyCPU:

  • 将x86和x64程序集安装到GAC中:它们可以(应该!)具有相同的程序集名称,GAC将自动决定是使用x86还是x64版本。

  • Hook into AppDomain。AssemblyResolve并使用Assembly从子目录中提供正确的程序集。LoadFrom

Oracle的ODP也存在类似的问题。. NET vs . native 32/64位OCI dll

我们已经解决了这个问题,为我们的项目创建了'x86'和'x64'平台,然后手动编辑我们的项目文件以使用条件引用:

<Choose>
<When Condition="'$(Platform)' == 'x64'">
  <ItemGroup>
    <Reference Include="Oracle.DataAccess, processorArchitecture=x64">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..'ThirdParty'ODP.NET'x64'Oracle.DataAccess.dll</HintPath>
    </Reference>
    <Content Include="..'ThirdParty'ODP.NET'x64'oci.dll">
      <Link>oci.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x64'orannzsbb11.dll">
      <Link>orannzsbb11.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x64'oraociei11.dll">
      <Link>oraociei11.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x64'OraOps11w.dll">
      <Link>OraOps11w.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</When>
<When Condition="'$(Platform)' == 'x86'">
  <ItemGroup>
    <Reference Include="Oracle.DataAccess, processorArchitecture=x86">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..'ThirdParty'ODP.NET'x86'Oracle.DataAccess.dll</HintPath>
    </Reference>
    <Content Include="..'ThirdParty'ODP.NET'x86'oci.dll">
      <Link>oci.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x86'orannzsbb11.dll">
      <Link>orannzsbb11.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x86'oraociei11.dll">
      <Link>oraociei11.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="..'ThirdParty'ODP.NET'x86'OraOps11w.dll">
      <Link>OraOps11w.dll</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</When>
</Choose>

这使我们能够避免使用两个不同的项目。我相信你也可以做类似的事情SQLite。

从开发的角度来看,这并不可怕,因为我们需要两个项目。

这不是真的-您可以在同一个项目中使用两个构建配置。在部署时,您需要同时构建x86和x64,但是代码库和项目可以是相同的。

我目前在一个更大的生产项目中这样做,这既是由于SQLite,也是由于其他包含x64和x86变体的本机/互操作库。

除非你的应用需要超过4gb的内存,否则通常情况下选择一是正确的。请记住,在64位操作系统上运行的32位应用具有64位的大多数优点,而没有许多缺点。这就是为什么x86是VS 2010中。exe应用程序的默认目标。

Branko Dimitrijevic说:"我相信您可以为SQLite做类似的事情。"这是正确的。:)

遇到同样的问题,我找到了罗德尼的问题和布兰科的答案,并自己尝试了一下。如果有人想看看我的工作SQLite实现,在这里:
<Choose>
  <When Condition="'$(Platform)' == 'x64'">
    <ItemGroup>
      <Reference Include="System.Data.SQLite, Version=1.0.88.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
        <SpecificVersion>False</SpecificVersion>
        <HintPath>System.Data.SQLite'x64'System.Data.SQLite.dll</HintPath>
      </Reference>
    </ItemGroup>
  </When>
  <When Condition="'$(Platform)' == 'x86'">
    <ItemGroup>
      <Reference Include="System.Data.SQLite, Version=1.0.88.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64">
        <SpecificVersion>False</SpecificVersion>
        <HintPath>System.Data.SQLite'x86'System.Data.SQLite.dll</HintPath>
      </Reference>
    </ItemGroup>
  </When>
</Choose>
<ItemGroup>
  <Reference Include="Microsoft.CSharp" />
  <Reference Include="System" />
  <Reference Include="System.configuration" />
  <Reference Include="System.Core" />
  <Reference Include="System.Windows.Forms" />
  <Reference Include="System.Xml.Linq" />
  <Reference Include="System.Data.DataSetExtensions" />
  <Reference Include="System.Data" />
  <Reference Include="System.Xml" />
</ItemGroup>

当然,您可以将HintPath命名为任何您喜欢的名称。

我发现这是一个完美的解决方案:我可以维护一个项目,并根据需要在目标平台之间快速切换。唯一潜在的缺点是我无法在解决方案资源管理器中看到引用。但是对于整个功能来说,这只是一个很小的代价。

您也可以通过更改Visual Studio中的编译选项来解决这个问题:

在Visual Studio中更改编译设置:

    进入程序的启动项目。
  1. 点击编译选项卡
  2. 点击高级编译选项。
  3. 将目标CPU选项更改为x86

你的程序现在将始终以32位模式运行,即使在64位机器上运行。

您还可以提供两个发行版,如上所述,每个发行版对应一个环境。虽然这将成为未来的标准,但对于我当前的项目来说,这是最好和最简单的选择。

这是一个老问题,但我遇到了同样的问题,自2017年以来一直使用SQLite的项目。

我首先升级到最新版本的System.Data.Sqlite。核心,1.0.118。它有两个互操作垫片,一个用于x86,另一个用于x64。升级是用Nuget完成的。

将我们的项目更改为在混合模式下构建,它在32和64个Windows上都可以很好地工作。除了我们的安装套件现在添加了这两个文件之外,不需要其他更改。