问题描述
我正在尝试为无法更改 App.config 的应用程序制作一个使用 EF6.1 和 SQLite 的插件,因此需要在代码中设置所有配置和连接字符串.
I'm trying to make a plug in that will use EF6.1 and SQLite for an app where I can't change the App.config so all the configuration and connection string needs to be set in code.
我发现这个答案看起来很有希望使用实体框架的问题6 和 SQLite
I found this answer that looked promising Problems using Entity Framework 6 and SQLite
所以现在我有一个这样的配置类:
So now I have a configuration class like this:
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);
}
}
我已经确认这在第一次创建上下文和所有这些返回值之前就被命中了.
I have confirmed this gets hit before the context is created for the first time and all these return values.
我的上下文是这样的
public class MyContext : DbContext
{
public MyContext(string connectionString)
: base(connectionString) { }
public DbSet<MyEntity> MyEntities { get; set; }
}
我有一些代码这样称呼它:
And I have some code calling it like this:
var context = new MyContext("Data Source = mytest.db; Version = 3;");
var entities = context.MyEntities.ToList();
当我尝试运行代码时,看起来上下文假设连接字符串是用于 SQL Server 的,因为它给了我:
When I try and run the code it looks like the context is assuming the connection string is for SQL Server as it gives me:
不支持关键字:版本".
Keyword not supported: 'version'.
如果我删除它,我会收到一个错误,指出它无法连接并且它显然正在尝试连接到 SQL Server 数据库.
If I remove it I then get an error that it cannot connect and its clearly trying to connect to a SQL Server database.
我尝试通过添加构造函数来传递 SQLite 连接:
I tried passing in a SQLite connection by adding a constructor:
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.Data.SQLite.SQLiteConnection"的连接的 DbProviderFactory 类型.确保在应用程序配置中安装或注册了 ADO.NET 提供程序.
Unable to determine the DbProviderFactory type for connection of type 'System.Data.SQLite.SQLiteConnection'. Make sure that the ADO.NET provider is installed or registered in the application config.
所以我做了一个工厂解析器并注册了它
So I made a factory resolver and registered that
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());
但现在我明白了:
找不到具有不变名称System.Data.SQLite.EF6"的 ADO.NET 提供程序的实体框架提供程序.确保提供程序已在应用程序配置文件的entityFramework"部分注册.请参阅 http://go.microsoft.com/fwlink/?LinkId=260882了解更多信息.
No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SQLite.EF6'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
我已经在这方面做了两天了,但我的想法已经不多了.
I've beet at this for two days now and I'm running out of ideas.
推荐答案
至少需要一个自定义的IProviderInvariantName
, IDbDependencyResolver
和<代码>数据库配置:
The minimum needed to make the constructor with connection string working is a custom IProviderInvariantName
, IDbDependencyResolver
and 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
:
Update: For NET4.0 you would also need a custom 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
方法实现.
这篇关于EF6,如果没有 App.config,SQLite 将无法工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!