[英]Options for using System.Data.SQLite in a 32bit and 64bit C# world
我理解為什么在32位和64位版本中提供System.Data.SQLite.dll。 所以我們不要再糾纏於此並繼續前進。 :)
由於它以這種方式完成,它似乎使得純粹的C#開發更難以做出3個選擇。
是僅支持32位並強制使用托管程序集來編譯x86並在32或64位運行時處理它,並且當你在64位環境中時會失去優勢。
是強制64位並且僅支持64位並且失去了在32位上運行的能力但是獲得了64位的所有優點。
是創建兩個版本的程序集,一個編譯x86並使用32位SQLite,另一個編譯x64並使用64位SQLite。 它阻止使用“ANY”作為編譯選項,並且能夠輕松地將單個構建部署到任一類型。 從開發的角度來管理並不是那么可怕,因為我們需要兩個項目。 只將C#代碼正式放在一個,而另一個只使用“鏈接”到另一個代碼。 這僅用於編譯目的。 仍然讓我們必須管理兩個輸出以進行部署。
盡管如此,我只是在尋找確認以上是唯一正確的選擇。
如果我還有其他選擇,請告訴我。 具體來說,如果有方法可以獲得一個可以編譯為ANY的單個C#DLL,那么它可以利用32位或64位,具體取決於它的運行位置並仍然使用System.Data.SQLite.dll。
這是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版本。
使用Assembly.LoadFrom掛鈎到AppDomain.AssemblyResolve並從子目錄提供正確的程序集
Oracle的ODP.NET與本機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>
這使我們能夠避免使用2個不同的項目。 我相信你可以為SQLite做類似的事情。
從開發的角度來管理並不是那么可怕,因為我們需要兩個項目。
事實並非如此 - 您可以在同一個項目中使用兩個構建配置。 在部署時,您需要為x86和x64構建,但代碼庫和項目可以是相同的。
我目前在一個更大的生產項目中執行此操作,這既包括SQLite,也包括其他包含x64和x86變體的本機/互操作庫。
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命名為您喜歡的任何名稱。
我發現這是一個完美的解決方案:我可以維護一個項目,並根據需要在目標平台之間快速切換。 唯一可能的缺點是我無法在解決方案資源管理器中看到參考。 但這是為整體功能付出的小代價。
除非您的應用程序需要超過4GB的內存,否則通常選擇一種方法。 請記住,64位操作系統上的32位應用程序具有64位的大部分優點,沒有許多缺點。 這就是為什么x86是VS 2010中.exe應用程序的默認目標。
您還可以通過更改Visual Studio中的編譯選項來解決此問題:
要在Visual Studio中更改編譯設置:
您的程序現在將始終以32位模式運行,即使在64位計算機上運行也是如此。
您還可以提供兩個分發,一個針對上面提到的每個環境。 雖然這將成為未來的標准,但對於我目前的項目來說,這是最好和最簡單的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.