EF6 with SQLite in .NET 4.0 Code-Based Configuration: "Unable to Determine the DbProviderFactory"

.net-4.0 c# ef-code-first entity-framework-6

Question

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.

1
5
5/23/2017 11:46:36 AM

Popular Answer

Here I found suggestion that helped me configure sqlite with EF6 programatically.

Code block from that answer:

var dataRow = dbProviderFactoriesDataTable.Rows.OfType<DataRow>()
                    .FirstOrDefault(x => x.ItemArray[2].ToString() == assemblyName);

if (dataRow != null)
    dbProviderFactoriesDataTable.Rows.Remove(dataRow);

is equivalent to:

<remove invariant="" />
0
5/23/2017 11:46:36 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow