web-dev-qa-db-fra.com

Problèmes liés à Entity Framework 6 et SQLite

J'essaie d'utiliser Entity Framework avec SQLite. J'ai eu des problèmes pour l'intégrer dans mon application principale, alors j'ai commencé un petit test à partir de zéro, en suivant exactement les instructions sur http://brice-lambson.blogspot.com/2012/10/entity-framework-on- sqlite.html

Après tout, je reçois le message d'erreur suivant lors de l'exécution du projet:

Aucun fournisseur Entity Framework trouvé pour le fournisseur ADO.NET avec le nom invariant 'System.Data.SQLite'. Assurez-vous que le fournisseur est enregistré dans la section 'entityFramework' du fichier de configuration de l'application. Voir http://go.Microsoft.com/fwlink/?LinkId=260882 pour plus d'informations.

Mon app.config ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.Microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <add name="SQLite Data Provider"
            invariant="System.Data.SQLite"
            description="Data Provider for SQLite"
            type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="ChinookContext"
          connectionString=
"Data Source=|DataDirectory|Chinook_Sqlite_AutoIncrementPKs.sqlite"
          providerName="System.Data.SQLite" />
  </connectionStrings>
</configuration>

Ensuite, j'ai vu son article sur Entity Framework 6. Bien que ce ne soit pas l'erreur exacte que j'ai eu, j'ai essayé d'installer son fournisseur mis à jour via NuGet. L'erreur était partie, mais remplacée par celle-ci:

Impossible de charger le fichier ou l'assembly 'System.Data.SQLite.Linq, Version = 2.0.88.0, Culture = neutre, PublicKeyToken = db937bc2d44ff139' ou l'une de ses dépendances. La définition du manifeste de l'Assemblée localisée ne correspond pas à la référence de l'Assemblée. (Exception de HRESULT: 0x80131040)

De plus, mon app.config a été modifié (légèrement) en ceci:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.Microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.SQLiteProviderServices, System.Data.SQLite.Linq, Version=2.0.88.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description="Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
      <remove invariant="System.Data.SQLite" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="ChinookContext" connectionString="Data Source=|DataDirectory|Chinook_Sqlite_AutoIncrementPKs.sqlite" providerName="System.Data.SQLite" />
  </connectionStrings>
</configuration>

J'ai tout essayé pour résoudre ces erreurs, rien n'a fonctionné. J'ai essayé d'utiliser les autres binaires SQLite; J'ai essayé de modifier manuellement le projet SQLite pour utiliser EF version 6; J'ai changé les architectures, j'ai ajouté et supprimé les paquets de nuget, etc.

Je ne sais pas ou aller d'ici.

42
Xcelled

Sur la base du commentaire de magicandre1981, j'ai commencé à examiner de plus près la syntaxe du nœud fournisseur. J'ai trouvé que mon assemblage était une version différente de celle spécifiée dans l'attribut type, bien que je n'aie ni inséré ni touché cette ligne. En supprimant le nom fort, j'ai obtenu .Net pour charger la bibliothèque. Pour référence, voici la nouvelle ligne:

<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.SQLiteProviderServices, System.Data.SQLite.Linq" />

Cela m'a remis sur la bonne voie et j'ai pu faire correspondre mes résultats à ceux du blog.

Je me dois toutefois de noter que j'ai décidé que SQLite ne convient pas à Entity Framework, car il manque trop de fonctions critiques. Je suis passé à SQL Server Compact Edition, que j'ai installé via NuGet. Un simple tweak à ma chaîne de connexion et je courais avec toute la puissance de Entity Framework. Cela a pris moins d'une minute, comparé au slog de plusieurs heures qu'est SQLite. Si possible, je vous recommande de changer de base de données. System.Data.SQLite n'est tout simplement pas prêt pour Entity Framework.

23
Xcelled

Je pensais que je partagerais un autre moyen de configurer EF6 avec SQLite sans utiliser app.config/web.config. EF6 prend désormais en charge les configurations basées sur le code, comme indiqué ici sur msdn . J'ai utilisé le code suivant (mis à jour pour supprimer les reflets grâce à Sly):

public class SQLiteConfiguration : DbConfiguration
{
    public SQLiteConfiguration()
    {
        SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
        SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
        SetProviderServices("System.Data.SQLite", (DbProviderServices)SQLiteProviderFactory.Instance.GetService(typeof(DbProviderServices)));
    }
}

J'utilise ceci pour pouvoir injecter le bon DbContext et donc DbProvider au moment de l'exécution, sans avoir besoin de tout configurer dans l'assembly principal.

Modifier:

Comme Reyn a dit vous aurez aussi besoin d’ajouter un IDbConnectionFactory pour SQLite si vous souhaitez avoir votre chaîne de connexion dans votre web.config/app.config fichier. Une autre approche consiste à appeler un constructeur de base différent de votre DbContext, qui transmet un nouveau SQLiteConnection plutôt que la chaîne de connexion, comme indiqué dans cette réponse .

55
kjbartel

Je sais que c'est une vieille question, mais personne ne semble avoir fourni de réponse qui utilise réellement le fichier .config. Voici les sections system.data et entityframework de mon web.config qui permettent les connexions aux bases de données SQLServer et Sqlite:

<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" />
      <remove invariant="System.Data.SQLite" />
      <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>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SQLite.EF6" 
          type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
      <provider invariantName="System.Data.SqlClient" 
          type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite" 
          type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
30
Clever Human

Pour tous ceux qui utilisent la configuration basée sur le code et obtiennent toujours la même exception: je devais également définir la fabrique de connexions dans la réponse de kjbartel.

public class SQLiteConnectionFactory : IDbConnectionFactory
{
    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        return new SQLiteConnection(nameOrConnectionString);
    }
}

Puis définissez la fabrique de connexions par défaut dans SQLiteConfiguration

public class SQLiteConfiguration : DbConfiguration
{        
    public SQLiteConfiguration()
    {
        SetDefaultConnectionFactory(new SQLiteConnectionFactory());
        SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance);
        SetProviderFactory("System.Data.SQLite.EF6", SQLiteProviderFactory.Instance);
        Type t = Type.GetType( "System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6");
        FieldInfo fi = t.GetField("Instance", BindingFlags.NonPublic | BindingFlags.Static);
        SetProviderServices("System.Data.SQLite", (DbProviderServices)fi.GetValue(null));
    }
}
15
Reyn