Варианты использования System.Data.SQLite в 32-битном и 64-битном мире C # - PullRequest
21 голосов
/ 01 сентября 2011

Я понимаю, ПОЧЕМУ 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. Это предотвращает использование «ЛЮБОГО» в качестве опции компиляции и возможность легко развернуть одну сборку для любого типа. это не так ужасно управлять с точки зрения развития, как мы понадобятся два проекта. Только официально имея код C # в одном, а другой будет просто использовать «ссылки» на код в другом. это только для целей компиляции. Все еще оставляет нас с необходимостью управлять двумя выходами для развертываний.

С учетом всего вышесказанного, я только ищу подтверждение того, что вышесказанное является единственным правильным выбором.

Если, однако, есть другие варианты, которые я пропускаю, пожалуйста, дайте мне знать. В частности, если есть способ получить одну C # DLL, которая может быть скомпилирована в ЛЮБУЮ, так что она может использовать 32- или 64-битные преимущества в зависимости от того, где она запускается, и при этом использовать System.Data.SQLite.dll.

Ответы [ 7 ]

21 голосов
/ 15 марта 2012

Это уточнение ответа от 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. Лично у меня были хорошие результаты с теми в этом пакете NuGet: http://www.nuget.org/packages/SQLitex64

(Вам нужно только использовать пакет NuGet, чтобы получить скомпилированные SQLite Dlls. Как только вы их получите, удалите ссылку на SQLite в вашем проекте, созданном NuGet, и сам пакет NuGet. Действительно, оставив ссылку на месте может помешать этому решению, так как SQLite никогда не будет распознан как неразрешенная сборка.)

Вызывайте 'HandleUnresolvedAssemblies ()' как можно раньше, желательно во время любой начальной загрузки.

14 голосов
/ 12 сентября 2011

Существует 2 распространенных решения для хранения вашего основного приложения в AnyCPU:

  • Установите сборки x86 и x64 в GAC: они могут (должны!) Иметь одинаковые имена сборок, и GAC автоматически решит, использовать версию x86 или x64.

  • Подключитесь к AppDomain.AssemblyResolve и обслуживайте нужные сборки из подкаталогов, используя Assembly.LoadFrom

6 голосов
/ 01 сентября 2011

Аналогичная проблема существует с Oracle ODP.NET в сравнении с собственными 32/64-битными DLL-библиотеками OCI.

Мы решили эту проблему, создав платформу «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.

3 голосов
/ 01 сентября 2011

Управлять с точки зрения разработки не так уж и страшно, поскольку нам понадобятся два проекта.

Это не так - вы можете использовать две конфигурации сборки в одном проекте.Во время развертывания вам нужно будет собрать как для x86, так и для x64, но база кода и проект могут совпадать.

В настоящее время я делаю это в более крупном производственном проекте, обаиз-за SQLite, а также других встроенных / взаимодействующих библиотек, включающих варианты x64 и x86.

2 голосов
/ 31 августа 2013

Бранко Димитриевич сказал: «Я уверен, что вы можете сделать что-то подобное для 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 как угодно.

Я считаю, что это идеальное решение: я могу поддерживать один проект и быстро переключаться между целевыми платформами по мере необходимости. Единственный потенциальный недостаток - я не вижу ссылку в обозревателе решений. Но это небольшая цена за полную функциональность.

2 голосов
/ 01 сентября 2011

Обычно первым вариантом будет вариант, если вашему приложению не требуется более 4 ГБ памяти. Помните, что 32-битное приложение в 64-битной ОС обладает большинством 64-битных преимуществ без многих недостатков. Вот почему x86 является целью по умолчанию для приложений .exe в VS 2010.

0 голосов
/ 16 мая 2013

Вы также можете решить эту проблему, изменив параметры компиляции в Visual Studio:

Чтобы изменить параметры компиляции в Visual Studio:

  1. Перейдите к стартовому проекту вашей программы..
  2. Откройте окно свойств.
  3. Перейдите на вкладку компиляции.
  4. Выберите дополнительные параметры компиляции.
  5. Измените параметры целевого процессора на x86.

Ваша программа теперь всегда будет работать в 32-битном режиме, даже если она выполняется на 64-битной машине.

Вы также можете предоставить два дистрибутива, по одному для каждой среды, как указано выше.Хотя в будущем это станет стандартом, для моего текущего проекта это был лучший и самый простой вариант.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...