I am trying to get EF6 Code-Based Configuration to work with SQLite in .NET 4.0. In my target application App.config
is auto-generated so editing that is very painful. Initially when installing EF6 to SQLite through NuGet to my test application it generates the following configuration that works:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" />
</startup>
<system.data>
<DbProviderFactories>
<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>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<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" />
</providers>
</entityFramework>
</configuration>
On SQL Server CE I was able to just copy the contents of the App.config
to a DbConfiguration class. Similarly I tried:
class DBConfig : DbConfiguration
{
public DBConfig() : base()
{
this.SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0"));
this.SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
this.SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
this.SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
this.SetProviderServices("System.Data.SQLite.EF6", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
}
}
But when creating the Context by giving the constructor SQLiteConnection or connectionString this yields me the System.NotSupportedException:
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.
at System.Data.Entity.Infrastructure.Net40DefaultDbProviderFactoryResolver.<>c__DisplayClass5.<GetProviderFactory>b__0(Type t)
at System.Collections.Concurrent.ConcurrentDictionary'2.GetOrAdd(TKey key, Func'2 valueFactory)
at System.Data.Entity.Infrastructure.Net40DefaultDbProviderFactoryResolver.GetProviderFactory(DbConnection connection, IEnumerable'1 dataRows)
at System.Data.Entity.Infrastructure.Net40DefaultDbProviderFactoryResolver.ResolveProviderFactory(DbConnection connection)
at System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderFactory(DbConnection connection)
at System.Data.Entity.Core.Common.DbProviderServices.GetProviderFactory(DbConnection connection)
at System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInvariantName(DbConnection connection)
at System.Data.Entity.Internal.InternalConnection.get_ProviderName()
at System.Data.Entity.Internal.LazyInternalContext.get_ProviderName()
at System.Data.Entity.Internal.DefaultModelCacheKeyFactory.Create(DbContext context)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet'1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet'1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet'1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet'1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
I have tried:
- adding
SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
according to this answer. - adding
AddDependencyResolver(new SingletonDependencyResolver<DbProviderFactory>(SQLiteProviderFactory.Instance));
and DependencyResolvers for DbProviderServices and IDbConnectionFactory and even tried setting them ad DefaultResolvers. - creating my own SQLiteConnectionFactory and setting it as default according to this answer.
I remember reading somewhere that if there is a <System.Data>
section in Machine.config
file it may cause confusion in the ProviderFactories. Is there any code-based configuration equivalent to <remove invariant="" />
?
Also the SQLiteProviderService class is internal and the only way to get is through reflection according to this answer. Is the program truly able to access the service? This seems to work for most people though.
Any help or ideas to try and solve this well appreciated!
A curious note: when creating a SQLiteConnection from SQLiteProviderFactory.Instance.CreateConnection()
the DbProviderFactory property of the connection is System.Data.SQLite.SQLiteFactory
but with the working App.config
configuration System.Data.Entity.Core.Common.DbProviderServices.GetProviderFactory(connection)
returns SQLiteProviderFactory
. Whereas with code-based configuration it throws.