C# 类库中的SQLite。找不到数据库提供程序

C# 类库中的SQLite。找不到数据库提供程序,c#,entity-framework,sqlite,class-library,C#,Entity Framework,Sqlite,Class Library,我们有一个类库处理所有与数据库相关的操作。(SQLite和MSSQL)我试图去掉可执行项目中的所有提供者和工厂(),因为类库在App.config中已经有了DB配置 <entityFramework> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityF

我们有一个类库处理所有与数据库相关的操作。(SQLite和MSSQL)我试图去掉可执行项目中的所有提供者和工厂(),因为类库在App.config中已经有了DB配置

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


如果我将提供程序添加到可执行文件中的App.config,它确实可以工作。但这正是我试图避免的。这个问题有什么解决方案吗?

为了支持EF6数据库提供程序w/o app.config,通常需要使用
SetProviderFactory
SetProviderServices
方法分别注册相应的
DbProviderFactory
DbProviderServices
派生类

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

假设您的类库项目引用了
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;
    }
}
就这些。您可以从类库项目中删除app.config,并可以从可执行文件app.config中使用如下连接字符串:

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

和EF6文档的相关主题。请注意类库不是应用程序,所以应用程序配置文件实际上是指可执行配置文件。无法使用类库配置文件强制EF6,因此基于代码的配置和可执行配置文件是唯一的选项

但这正是我不想做的。我想去掉可执行文件中的配置文件。你不需要任何配置文件-上面的代码配置可以帮你完成。但是您已经在某个地方命名了连接字符串(为了指定提供者名称),对吗?他们目前在哪里?我想不可能是在图书馆的项目里。那是真的。它们在可执行文件中。但是,可执行文件使用连接字符串从库中调用DAL。因此,可执行文件中不需要提供程序信息。此外,连接字符串以不典型的方式存储。(自己的XML结构)所以我们很好。没有供应商信息,没有工厂信息。没有
,在可执行app.config中没有
,只有
。我在这里已经有了类似的工作解决方案,只是它仅适用于SQLite,而上面的解决方案将适用于SQLite和SqlServer。EF6在包含db上下文的程序集(在您的例子中是类库项目)中搜索从
DbConfiguration
派生的类,并自动实例化它们,因此构造函数调用在运行时注册必要的信息,从而有效地消除了对配置文件的需要。我认为从解决方案的解释来看这是很清楚的(否则就没有意义了)。只需将上述3个类添加到类库中,您就会看到。
<add name="MyDb_SQLite" providerName="System.Data.SQLite.EF6" connectionString="Data Source =|DataDirectory|MyDb.sqlite" />