2011-08-31 42 views
21

Tôi hiểu TẠI SAO System.Data.SQLite.dll được cung cấp trong các bản dựng 32 bit và 64 bit. Vì vậy, cho phép không sống trên đó và di chuyển trên. :)Tùy chọn để sử dụng System.Data.SQLite trong 32bit và 64bit C# world

Vì nó được thực hiện theo cách này có vẻ như làm cho việc phát triển C# tinh khiết trở nên khó khăn hơn với 3 lựa chọn để thực hiện.

  1. Là để chỉ hỗ trợ 32-bit và lực lượng có quản lý lắp ráp để biên dịch x86 và đối phó với điều đó trong việc điều hành trong 32 hoặc 64 chút, và có bằng lợi thế mất khi bạn đang ở trên một 64 bit môi trường.

  2. Bắt buộc 64 bit và chỉ hỗ trợ 64 bit và mất khả năng chạy trên 32 bit nhưng đạt được tất cả các ưu điểm của 64 bit.

  3. Để tạo hai phiên bản của assembly, biên dịch x86 và sử dụng SQLite 32 bit và một phiên bản khác biên dịch x64 và sử dụng SQLite 64 bit. Nó ngăn cản việc sử dụng "BẤT CỨ" làm tùy chọn biên dịch và có thể dễ dàng triển khai một bản dựng duy nhất cho một trong hai loại. của nó không quá khủng khiếp để quản lý từ một quan điểm phát triển vì chúng tôi sẽ cần hai dự án. Chỉ có mã C# chính thức trong một, và người kia sẽ chỉ sử dụng "liên kết" với mã trong phần còn lại. chỉ dành cho mục đích biên dịch. Vẫn để chúng tôi phải có quản lý hai kết quả đầu ra để triển khai.

Với tất cả những gì đã nói, tôi chỉ tìm kiếm xác nhận rằng đây là lựa chọn đúng duy nhất.

Nếu có lựa chọn nào khác mà tôi nhìn thấy, vui lòng cho tôi biết. Cụ thể nếu có cách để có được một C# DLL duy nhất có thể biên dịch để BẤT CỨ vì vậy nó có thể tận dụng lợi thế của 32 hoặc 64 bit tùy thuộc vào nơi nó chạy và vẫn còn sử dụng System.Data.SQLite.dll.

+0

Có vẻ cho đến nay từ các ý kiến ​​rằng nó được xác nhận rằng không có không có tùy chọn ONE DLL có thể hỗ trợ BẤT CỨ CPU nền tảng giải pháp mục tiêu với SQLite như là một phụ thuộc. –

+0

Bạn nên cài đặt nó từ nuget. Vui lòng tham khảo [câu trả lời này] [1]. [1]: http://stackoverflow.com/a/19623876/2550529 – SepehrM

+0

NuGet không thực sự giải quyết vấn đề trong tầm tay với câu hỏi rất rất cũ này từ tháng 8 năm 2011 mà đã được trả lời. Ngoài ra NuGet không phải là một khả năng trong tất cả các cửa hàng phát triển, do đó, không phải luôn luôn là một lựa chọn ngay cả khi nó là giải pháp tốt nhất cho một vấn đề. Tôi đã thực sự phát triển đến một giải pháp tốt hơn trong những năm cho phép cho một lắp ráp wrapper đó là BẤT CỨ CPU và hỗ trợ đúng 32 và 64 bit SQLite hương vị năng động tại thời gian chạy. Tuy nhiên đây là một vấn đề cũ đã bị đóng nên mọi người nên chuyển sang phần hỏi đáp gần đây nhất là thời đại phần mềm. –

Trả lời

14

Có 2 giải pháp phổ biến để giữ cho ứng dụng chính của bạn tại AnyCPU:

  • Cài đặt cả x86 và các hội đồng x64 vào GAC: Họ có thể (!) Nên có tên lắp ráp giống hệt nhau và GAC sẽ tự động quyết định có sử dụng phiên bản x86 hoặc x64 hay không.

  • Hook vào AppDomain.AssemblyResolve và phục vụ các hội đồng ngay từ thư mục con bằng Assembly.LoadFrom

+0

Bạn có thể cài đặt nó từ nuget. Tham khảo: http: // stackoverflow.com/questions/19623823/sqlite-with-vs2012-và-net-4-5-any-cpu-build/19623876 # 19623876 – SepehrM

3

Nó không quá khủng khiếp để quản lý từ một quan điểm phát triển vì chúng tôi sẽ cần hai dự án.

Điều đó không đúng - bạn có thể sử dụng hai cấu hình xây dựng trong cùng một dự án. Tại thời điểm triển khai, bạn sẽ cần phải xây dựng cho cả x86 và x64, nhưng mã cơ sở và dự án có thể giống nhau.

Tôi hiện đang làm điều này trong một dự án sản xuất lớn hơn, cả do SQLite, nhưng cũng có các thư viện gốc/interop khác bao gồm các biến thể x64 và x86.

+0

Đó là cơ bản giống như những gì tôi đã nói chỉ cần tự hack các tập tin dự án để làm điều đó. Bạn vẫn kết thúc với HAI được quản lý DLL của một 32bit và 64bit. –

+0

Đây chỉ là biến thể của Tùy chọn 3 với cùng kết quả. Mục tiêu của câu hỏi là tìm ra tùy chọn MỚI với kết quả MỚI giúp bạn xây dựng mục tiêu nền tảng BẤT CỨ CPU làm việc với SQLite như một sự phụ thuộc. –

+3

@Rodney: Vâng, đây là biến thể của Tùy chọn 3 - nhưng nó sẽ lấy đi một trong những cơn đau chính với Tùy chọn 3 ở chỗ bạn không phải duy trì hai dự án ... –

2

Thông thường, tùy chọn sẽ là một cách để đi trừ khi ứng dụng của bạn cần nhiều hơn 4GB bộ nhớ. Hãy nhớ rằng một ứng dụng 32 bit trên một hệ điều hành 64bit có hầu hết các ưu điểm của 64bit mà không có nhiều nhược điểm. Đó là lý do tại sao x86 là mục tiêu mặc định cho các ứng dụng .exe trong VS 2010.

+1

Đúng và không chỉ lợi thế bộ nhớ , nhưng đó là một trong những đáng chú ý nhất. Có vấn đề truy cập 64 bit khu vực của hệ điều hành từ một thế giới 32 bit, và bạn nếu bạn sống nó yo phải biết làm thế nào để cơ động xung quanh trong này, nơi bạn thường không phải lo lắng về những điều này thêm với một BẤT CỨ xây dựng. –

6

Sự cố tương tự tồn tại với ODP.NET của Oracle với 32/64-bit OCI DLL.

Chúng tôi đã giải quyết nó bằng cách đóng thùng cả 'x86' và nền tảng 'x64' cho dự án của chúng tôi và sau đó tự chỉnh sửa tập tin dự án của chúng tôi để sử dụng tài liệu tham khảo có điều kiện:

<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> 

Điều này cho phép chúng tôi để tránh sử dụng 2 khác nhau dự án. Tôi chắc rằng bạn có thể làm điều gì đó tương tự cho SQLite.

+0

Vâng, đó là một giải pháp duy trì khó khăn hơn bởi vì việc hack các file dự án bằng tay tạo ra các thông tin ẩn mà không phải tất cả các nhà phát triển đến cùng sẽ biết, đó là lý do tại sao chúng tôi đã chọn không cho các dự án kép thực hiện việc này tập tin. Ngoài ra vẫn còn có hai DLL để quản lý như đầu ra. –

+0

Đây chỉ là biến thể của Tùy chọn 3 với cùng kết quả. Mục tiêu của câu hỏi là tìm ra tùy chọn MỚI với kết quả MỚI giúp bạn xây dựng mục tiêu nền tảng BẤT CỨ CPU làm việc với SQLite như một sự phụ thuộc. –

+4

@Rodney Mục tiêu của giải pháp này là để tránh 2 dự án, và theo nghĩa đó, nó là "mới". Tôi không bao giờ tuyên bố nó sẽ có thể đạt được "Bất kỳ CPU". BTW, đây không phải là thực sự "hack" - đây là cú pháp MSBuild được ghi chép đầy đủ. Nếu dự án của bạn là gốc của hệ thống phân cấp dự án thì có 2 dự án có thể là một giải pháp sạch hơn. Tuy nhiên, nếu nó nằm dưới 10 mức phụ thuộc (như trong trường hợp của chúng ta), thì tôi tin rằng cũng đáng để tránh phải sao chép tất cả các phụ thuộc. –

21

Đây là một xây dựng câu trả lời từ Springy76. Thực hiện việc này:

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; 
    } 
} 

Đảm bảo đường dẫn được tạo đến đúng vị trí cho các tệp 32 bit hoặc 64 bit SQLite của bạn. Cá nhân tôi đã có kết quả tốt với những người trong gói NuGet này: http://www.nuget.org/packages/SQLitex64

(Bạn chỉ cần sử dụng gói NuGet để giữ các tệp SQLite được biên dịch. Khi bạn đã có chúng, hãy xóa tham chiếu đến SQLite trong dự án của bạn được tạo ra bởi NuGet và gói NuGet chính nó. Thật vậy, để tham chiếu tại chỗ có thể can thiệp vào giải pháp này vì SQLite sẽ không bao giờ được công nhận là một hội đồng chưa được giải quyết.)

Gọi 'HandleUnresolvedAssemblies()' càng sớm càng tốt, tốt nhất là trong bất kỳ Bootstrapping nào.

+0

Nhưng với tham chiếu đến các dll bị xóa, mã không thể tìm thấy không gian tên và các phương thức lớp này và không thể biên dịch được. Làm thế nào để bạn giải quyết điều này? – DefenestrationDay

+0

Giải pháp này hoạt động cho các tình huống mà bạn đang sử dụng các thư viện khác xử lý công việc giao tiếp với SQLite. Sử dụng nHibernate với SQLite là một ví dụ như vậy. Nếu bạn muốn truy cập trực tiếp vào các phương thức lớp thì bạn sẽ cần phải xem xét một giải pháp khác, chẳng hạn như mẹo xây dựng có điều kiện được đăng trong câu trả lời khác. – Holf

1

Bạn cũng có thể giải quyết điều này bằng cách thay đổi các tùy chọn biên dịch trong Visual Studio của bạn:

Để thay đổi các thiết lập của bạn biên dịch trong Visual Studio:

  1. Tới dự án khởi động của chương trình của bạn.
  2. Mở cửa sổ thuộc tính.
  3. Nhấp vào tab biên dịch.
  4. Nhấp vào tùy chọn biên dịch nâng cao.
  5. Thay đổi các tùy chọn CPU mục tiêu thành x86.

Chương trình của bạn bây giờ sẽ luôn chạy ở chế độ 32 bit, ngay cả khi chạy trên máy 64 bit.

Bạn cũng có thể cung cấp hai bản phân phối, một bản cho mỗi môi trường như đã đề cập ở trên. Trong khi điều này sẽ trở thành tiêu chuẩn trong tương lai, cho dự án hiện tại của tôi, đây là lựa chọn tốt nhất và dễ nhất.

2

Branko Dimitrijevic nói, "Tôi chắc rằng bạn có thể làm điều gì đó tương tự cho SQLite". Và đó là chính xác. :)

Có vấn đề rất giống nhau, tôi đã tìm thấy câu hỏi của Rodney và câu trả lời của Branko và tự mình thử nó.Đối với bất kỳ ai muốn xem triển khai SQLite hoạt động của tôi, ở đây bạn đi:

<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> 

Tất nhiên, bạn có thể đặt tên HintPath cho bất kỳ thứ gì bạn muốn.

Tôi thấy đây là giải pháp hoàn hảo: Tôi có thể duy trì một dự án duy nhất và nhanh chóng chuyển đổi giữa các nền tảng đích nếu cần. Nhược điểm tiềm năng duy nhất là tôi không thể thấy tham chiếu trong Solution Explorer. Nhưng đó là một mức giá nhỏ để trả cho chức năng tổng thể.

Các vấn đề liên quan