代码之家  ›  专栏  ›  技术社区  ›  Bin4ry

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

  •  3
  • Bin4ry  · 技术社区  · 7 年前

    with this approach )在可执行项目中,因为类库已经在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>
    

    enter image description here

    如果我将提供程序添加到可执行文件中的App.config中,它就会工作。但这是我尽量避免的。这个问题有什么解决办法吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Ivan Stoev    7 年前

    为了支持不带app.config的EF6数据库提供程序,通常需要 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());
        }
    }
    

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

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

    推荐文章