类库中的SQLite。找不到DB-Provider

问题描述 投票:3回答:1

我们有一个处理所有与DB相关的操作的类库。 (SQLite和MSSQL)我试图摆脱可执行项目中的所有提供者和工厂(with this approach),因为类库已经在App.config中有了DB-Configuration。

 <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,它确实有效。但这是我试图避免的。有没有解决这个问题的方法?

c# entity-framework sqlite class-library
1个回答
2
投票

为了支持没有app.config的EF6数据库提供程序,你通常需要DbConfiguration派生类,它分别使用DbProviderFactoryDbProviderServices方法注册相应的SetProviderFactorySetProviderServices

但是,这对SQLite提供程序来说还不够,因为它没有实现导致运行时异常的IProviderInvariantName服务。因此,您需要通过IDbDependencyResolver方法注册的自定义AddDependencyResolver添加该服务的实现。

假设您的类库项目引用了System.Data.SQLiteSystem.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" />

有关更多信息,请参阅Code-based configuration和EF6文档的相关主题。请注意,类库不是应用程序,因此应用程序配置文件实际上意味着可执行配置文件。无法使用类库配置文件强制EF6,因此基于代码的配置和可执行配置文件是唯一的选项。

© www.soinside.com 2019 - 2024. All rights reserved.