我们有一个处理所有与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抛出异常:
如果我将提供程序添加到可执行文件中的App.config中,它将起作用。但这就是我要避免的事情。这个问题有什么解决办法吗?
答案 0 :(得分:2)
为了支持不带app.config的EF6数据库提供程序,通常需要DbConfiguration
派生类,该派生类分别使用{{1}注册相应的DbProviderFactory
和DbProviderServices
}和SetProviderFactory
方法。
但是,对于SQLite提供程序来说,这还不够,因为它未实现SetProviderServices
服务,这会导致运行时异常。因此,您需要通过通过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;
}
}
仅此而已。您可以从类库项目中删除app.config,并能够从可执行的app.config中使用这样的连接字符串:
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());
}
}
有关更多信息,请参阅Code-based configuration和EF6文档的相关主题。请注意,类库不是 应用程序,因此 application 配置文件实际上意味着可执行配置文件。无法使用类库配置文件强制EF6,因此基于代码的配置和可执行文件是唯一的选择。