SQLite в библиотеке классов.БД-провайдер не найден - PullRequest
0 голосов
/ 24 августа 2018

У нас есть библиотека классов, занимающаяся всеми операциями, связанными с БД.(SQLite и MSSQL) Я попытался избавиться от всех провайдеров и фабрик ( с таким подходом ) в исполняемом проекте, поскольку библиотека классов уже имеет конфигурацию DB в App.config.

 <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
      <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>

  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite" />
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
      <remove invariant="System.Data.SQLite.EF6" />
      <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
    </DbProviderFactories>
  </system.data>

Однако, пока MSSQL работает нормально, SQLite выдает исключение:

enter image description here

Это работает, если я добавляю провайдерав App.config в исполняемом файле.Но это то, чего я стараюсь избегать.Есть ли решение этой проблемы?

1 Ответ

0 голосов
/ 02 сентября 2018

Для поддержки поставщика базы данных EF6 без app.config обычно требуется производный класс DbConfiguration, который регистрирует соответствующие DbProviderFactory и DbProviderServices, используя соответственно SetProviderFactory и SetProviderServices методы.

Однако этого недостаточно для поставщика SQLite, поскольку он не реализует службу IProviderInvariantName, которая вызывает рассматриваемое исключение времени выполнения. Таким образом, вам нужно добавить реализацию этой службы с помощью пользовательского IDbDependencyResolver, зарегистрированного с помощью AddDependencyResolver метода.

Предполагая, что в вашем проекте библиотеки классов есть ссылки на сборки System.Data.SQLite и System.Data.SQLite.EF6, а в строке подключения "System.Data.SQLite.EF6" используется providerName, добавьте следующие классы реализации в проект библиотеки классов:

using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.DependencyResolution;
using System.Data.SQLite.EF6;
using System.Data.SQLite;

class SQLiteProviderInvariantName : IProviderInvariantName
{
    public static readonly SQLiteProviderInvariantName Instance = new SQLiteProviderInvariantName();
    private SQLiteProviderInvariantName() { }
    public const string ProviderName = "System.Data.SQLite.EF6";
    public string Name { get { return ProviderName; } }
}

class SQLiteDbDependencyResolver : IDbDependencyResolver
{
    public object GetService(Type type, object key)
    {
        if (type == typeof(IProviderInvariantName))
        {
            if (key is SQLiteProviderFactory || key is SQLiteFactory)
                return SQLiteProviderInvariantName.Instance;
        }
        return null;
    }

    public IEnumerable<object> GetServices(Type type, object key)
    {
        var service = GetService(type, key);
        if (service != null) yield return service;
    }
}

Затем снова добавьте следующий класс конфигурации (или обновите существующий, если он у вас есть) в проект библиотеки классов, содержащий ваш контекстный класс:

using System.Data.Entity;
using System.Data.Entity.Core.Common;
using System.Data.SQLite.EF6;

class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration()
    {
        SetProviderFactory(SQLiteProviderInvariantName.ProviderName, SQLiteProviderFactory.Instance);
        SetProviderServices(SQLiteProviderInvariantName.ProviderName, (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
        AddDependencyResolver(new SQLiteDbDependencyResolver());
    }
}

И это все. Вы можете удалить app.config из проекта библиотеки классов и сможете использовать такие строки подключения из исполняемого файла app.config:

<add name="MyDb_SQLite" providerName="System.Data.SQLite.EF6" connectionString="Data Source =|DataDirectory|MyDb.sqlite" />

Для получения дополнительной информации см. Конфигурация на основе кода и соответствующие разделы документации EF6. Обратите внимание, что библиотеки классов являются , а не приложениями, поэтому файл конфигурации application действительно означает исполняемый файл конфигурации. Невозможно заставить EF6 использовать файл конфигурации библиотеки классов, поэтому конфигурация на основе кода и исполняемый файл конфигурации являются единственными опциями.

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