2017-04-25 65 views
14

我試圖做一個插件,將使用EF6.1和SQLite的應用程序,我不能更改App.config所以所有的配置和連接字符串需要在代碼中設置。EF6,SQLite將無法運行沒有App.confg

,我發現這個答案是那麼現在看起來前途無量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:

關鍵字不支持:'版本'。

如果我刪除它,然後得到一個錯誤,它無法連接,並顯然嘗試連接到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.Data.SQLite.SQLiteConnection」類型的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()); 

但現在我得到這樣的:

沒有實體框架提供發現的ADO.NET具有不變名稱「System.Data.SQLite.EF6」的提供者。確保提供程序在應用程序配置文件的'entityFramework'部分中註冊。有關更多信息,請參見http://go.microsoft.com/fwlink/?LinkId=260882

我已經在這個甜菜兩天了,現在我已經沒有想法了。

回答

13

,以與連接字符串工作的構造所需的最低是定製IProviderInvariantNameIDbDependencyResolverDbConfiguration

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方法實現。

+0

我給了這個嘗試,但現在我得到的錯誤消息:無法確定類型'System.Data.SQLite.SQLiteConnection'的連接DbProviderFactory類型。確保在應用程序配置中安裝或註冊了ADO.NET提供程序。 – Mant101

+0

這很奇怪,因爲我能夠完全按照您描述的方式複製問題,然後上面的問題解決了它。確保項目中沒有其他的'DbConfiguration'類(例如,在發佈的代碼中使用的類)和解析器 - 只是答案中的類。並且你使用連接字符串的構造函數,而不是連接。正如你所看到的,上面的'IDbDependencyResolver'暴力破解了'DbProviderFactory',所以不應該得到這樣的錯誤。 –

+0

如果您可以提供完整的repro項目,我可以看看它,但我相信這是解決方案,因爲我能夠連接/使用SQLite數據庫,並明確註釋掉了來自App.config的SQLite相關實體,以及保持localdb默認,SqlServer和MySQL –

相關問題