5

It is necessary to use the SQLite Entity Framework Database-first approach for the 3d-party application plugin. I searched all the Internet, including Add a DbProviderFactory without an App.Config, Problems using Entity Framework 6 and SQLite and many other. I have tried to use them all in different ways and combinations, but nothing helps:

"An unhandled exception of type 'System.Data.Entity.Core.MetadataException' occurred in mscorlib.dll. Additional information: Schema specified is not valid. Errors: AutosuggestModel.ssdl (2,2): error 0152: 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."

There is a test console application in the solution. With this minimal App.config it works:

<?xml version="1.0" encoding="utf-8"?>
<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>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    </DbProviderFactories>
  </system.data>
</configuration>

The connection string has already implemented in the code. Used packages are:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="EntityFramework" version="6.1.3" targetFramework="net452" />
  <package id="System.Data.SQLite" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.Core" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.EF6" version="1.0.98.1" targetFramework="net452" />
  <package id="System.Data.SQLite.Linq" version="1.0.98.1" targetFramework="net452" />
</packages>

Please, give all the required code and specify where to insert it. Thanks in advance.

4
  • the problem with sqlite and EF is: the database initializers are not working correctly, because Create database and Create table are not supported in the package (at least the versions I worked with). Your code does seem pretty weird. first you define the invariant System.Data.SQLite.EF6, and then you don't use it anymore. your problem is not really provider related, but code related. try renaming the invariant in the DbProviderFactories to "System.Data.SQLite.EF6", but maybe there are other errors I am missing here. Commented Sep 1, 2015 at 18:37
  • Thanks, but with such App.config all works correctly, and I already have database. I need the application to run without App.сonfig. With the help of answers by the links above, the section "system.data" can be deleted, but other sections still necessary. Commented Sep 1, 2015 at 19:36
  • ahh, you meant it like this. well you need your app.config in your case, because you let your DbContext know that way that EF has to use this connection type. There is an overload to the constructor of your DbContext that actually takes a SqlConnection, I think with this it might work, call like :base(new SQLiteConnection([connection string]),true) Commented Sep 1, 2015 at 21:11
  • Thanks again, but "the connection string has already implemented in the code". Commented Sep 1, 2015 at 21:39

1 Answer 1

5

Here is a sample code that illustrates how to achieve the goal.

namespace SqliteEFNoConfig
{
    using System.Configuration;
    using System.Data;
    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Core.Common;
    using System.Data.SQLite;
    using System.Data.SQLite.EF6;
    using System.Linq;

    internal class Program
    {
        private static void Main()
        {
            // EF manages the connection via the DbContext instantiation
            // connection string is set in config
            // Use this code if you want to use a config file
            // with only the connection string
            //using (var model = new Model1())
            //{
            //    var dbSetProperty = model.dbSetProperty.ToList();
            //}

            // Alternative method: 
            // Use this code if you don't want to use a config file
            // You will also need to use the override constructor shown below,
            // in your EF Model class
            var connectionString = @"data source = {PathToSqliteDB}";
            using (var connection = new SQLiteConnection(connectionString))
            {
                using (var model = new Model1(connection))
                {
                    var dbSetProperty = model.dbSetProperty.ToList();
                }
            }
        }
    }

    class SqliteDbConfiguration : DbConfiguration
    {
        public SqliteDbConfiguration()
        {
            string assemblyName = typeof (SQLiteProviderFactory).Assembly.GetName().Name;

            RegisterDbProviderFactories(assemblyName );
            SetProviderFactory(assemblyName, SQLiteFactory.Instance);
            SetProviderFactory(assemblyName, SQLiteProviderFactory.Instance);
            SetProviderServices(assemblyName,
                (DbProviderServices) SQLiteProviderFactory.Instance.GetService(
                    typeof (DbProviderServices)));
        }

        static void RegisterDbProviderFactories(string assemblyName)
        {
            var dataSet = ConfigurationManager.GetSection("system.data") as DataSet;
            if (dataSet != null)
            {
                var dbProviderFactoriesDataTable = dataSet.Tables.OfType<DataTable>()
                    .First(x => x.TableName == typeof (DbProviderFactories).Name);

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

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

                dbProviderFactoriesDataTable.Rows.Add(
                    "SQLite Data Provider (Entity Framework 6)",
                    ".NET Framework Data Provider for SQLite (Entity Framework 6)",
                    assemblyName,
                    typeof (SQLiteProviderFactory).AssemblyQualifiedName
                    );
            }
        }
    }
}

In case you decide to not add a connection string in the config file then you need to add the following constructor in the EF model.

public Model1(DbConnection connection)
    : base(connection, true)
{
}

Notice: The above code is just a sample on how to achieve the goal and you will have to adjust it accordingly to your needs. The above code is provided assuming you are using EF Code First approach.

Sign up to request clarification or add additional context in comments.

15 Comments

It doesn't work out of the box. You need to adjust it to your code. I specifically added the 'Notice' section for that reason.
I adjusted. But it's not working. Try it yourself. The goal is - console application must work after the removal of the App.config file.
It works. I just checked it again. You do realize that the first sample code in Main requires the config file but only the connection string to be present in it. And the 'Alternative method' doesn't need any config file at all. This is what I mean by 'you need to adjust it to your needs'.
You wrote "It works. I just checked it again." Please upload your example and give a link. I specifically asked in the question to give a complete working example.
Use only the alternative method. Remove any other code from Main. Needless to say that you also need to replace 'PathToSqliteDB' with the path to the sqlite db. And just for your FYI, I use the exact same sample without a config file in my console app. That's why I know it works.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.