我正在尝试插入一个将使用EF6.1和SQLite的应用程序用于我无法更改App.config的应用程序,因此需要在代码中设置所有配置和连接字符串
我发现这个答案很有希望Problems using Entity Framework 6 and SQLite
所以现在我有一个像这样的配置类:
public class CollectionDbConfiguration : DbConfiguration
{
public CollectionDbConfiguration()
{
SetProviderServices("System.Data.SQLite"(DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
}
}
我已经确认在第一次创建上下文并且所有这些返回值之前都会遇到此问题。
我的上下文看起来像这样
public class MyContext : DbContext
{
public MyContext(string connectionString)
: base(connectionString) { }
public DbSet<MyEntity> MyEntities { get; set; }
}
我有一些代码叫它:
var context = new MyContext("Data Source = mytest.db; Version = 3;");
var entities = context.MyEntities.ToList();
当我尝试运行代码时,看起来上下文假设连接字符串是针对SQL Server的,因为它给了我:
不支持关键字:&#39;版本&#39;。
如果我删除它,那么我会收到一个错误,它无法连接,并且显然正在尝试连接到SQL Server数据库。
我尝试通过添加构造函数传递SQLite连接:
public MyContext(DbConnection connection)
: base(connection, contextOwnsConnection: true)
{ }
用这个来称呼它:
var context = new MyContext(new SQLiteConnection("Data Source = mytest.db; Version = 3;"));
var entities = context.MyEntities.ToList();
但后来我收到了错误:
无法为类型&System; System.Data.SQLite.SQLiteConnection&#39;的连接确定DbProviderFactory类型。确保在应用程序配置中安装或注册了ADO.NET提供程序。
所以我做了一个工厂解析器并注册了
public class FactoryResolver : IDbProviderFactoryResolver
{
public DbProviderFactory ResolveProviderFactory(DbConnection connection)
{
if (connection.GetType() == typeof(SQLiteConnection))
{
return SQLiteFactory.Instance;
}
if (connection.GetType() == typeof(EntityConnection))
{
return SQLiteProviderFactory.Instance;
}
return null;
}
}
并补充道:
SetProviderFactoryResolver(new FactoryResolver());
但现在我明白了:
找不到具有不变名称&#39; System.Data.SQLite.EF6&#39;的ADO.NET提供程序的实体框架提供程序。确保提供商已在&#39; entityFramework&#39;中注册。应用程序配置文件的一部分。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=260882。
我现在已经好好炒了两天了,而且我已经没想完了。
答案 0 :(得分:13)
使连接字符串有效的构造函数所需的最小值是自定义IProviderInvariantName
,IDbDependencyResolver
和DbConfiguration
:
public 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)) return SQLiteProviderInvariantName.Instance;
if (type == typeof(DbProviderFactory)) return SQLiteProviderFactory.Instance;
return SQLiteProviderFactory.Instance.GetService(type);
}
public IEnumerable<object> GetServices(Type type, object key)
{
var service = GetService(type, key);
if (service != null) yield return service;
}
}
class SQLiteDbConfiguration : DbConfiguration
{
public SQLiteDbConfiguration()
{
AddDependencyResolver(new SQLiteDbDependencyResolver());
}
}
现在这应该有效:
var context = new MyContext("Data Source = mytest.db; Version = 3;");
var entities = context.MyEntities.ToList();
更新:对于NET4.0,您还需要自定义IDbProviderFactoryResolver
:
class SQLiteDbProviderFactoryResolver : IDbProviderFactoryResolver
{
public static readonly SQLiteDbProviderFactoryResolver Instance = new SQLiteDbProviderFactoryResolver();
private SQLiteDbProviderFactoryResolver() { }
public DbProviderFactory ResolveProviderFactory(DbConnection connection)
{
if (connection is SQLiteConnection) return SQLiteProviderFactory.Instance;
if (connection is EntityConnection) return EntityProviderFactory.Instance;
return null;
}
}
并添加
if (type == typeof(IDbProviderFactoryResolver)) return SQLiteDbProviderFactoryResolver.Instance;
到SQLiteDbDependencyResolver.GetService
方法实现。