EF6,如果没有App.config,SQLite将无法运行 [英] EF6, SQLite won't work without App.config

查看:258
本文介绍了EF6,如果没有App.config,SQLite将无法运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为无法更改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.

推荐答案

使具有连接字符串的构造函数正常工作所需的最低要求是自定义IProviderInvariantNameIDbDependencyResolverDbConfiguration:

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将无法运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆