none
Entity Framework 6 con SQLite RRS feed

  • Pregunta

  • Buenas,

    Estoy queriendo empezar a usar SQLite y con EF6, estoy viendo varios links de ejemplo, pero no me funcionan. Sigue creando la BD en SQL express y almacena ahí.

    Alguno sabe que debería hacer para funcione, utilizando Code First, con EF 6?.

    Agregué la referencia a System.Data.SQLite y a EF6

    Nose si será problema en la configuración en App.config o qué.

    Saludos!

    domingo, 6 de julio de 2014 1:12

Todas las respuestas

  • que quieres decir con que no funcionan?,puedes especificar mas? Algún mensaje de error? Gracias

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos

    domingo, 6 de julio de 2014 6:56
  • Buenas,

    Paso a describir la metodología y luego el error:

    1- Creo entidades, agrego el paquete de EF 6, creo el contexto. Sin DataAnnotations ni nada, sin especificar nada en el constructor del contexto.

    2- Agrego el paquete System.Data.SQLite

    3- Creo una BD y creo las tablas igual a las entidades (mismos nombres).

    4- Agrego el arhivo .sqlite al proyecto

    5- Acá es donde creo que está el problema, agrego una connectionString. En el App.Config, los ejemplos que veo, todos están distintos...

    Compilo y ejecuto, sale el siguiente error en tiempo de ejecución, después de querer guardar.

    using (var db = new ContextoMusical1())
                        {
                            Artist artista = new Artist();
                            artista.Name = nombreArtista;

                            db.Artists.Add(artista); //ERROR EN TIEMPO DE EJECUCION

                            db.SaveChanges();
                        }

    Error: 

    "The ADO.NET provider with invariant name 'System.Data.SQLite' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.

    InnerException.Message: No se encuentra el proveedor de datos .NET Framework solicitado. Puede que no esté instalado.

    Creo que el problema estaría en el App.Config:

    <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.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
        </providers>
      </entityFramework>
      
      <system.data>
        <DbProviderFactories>
          <!--<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" />-->
          <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>

      <connectionStrings>
        <add name="ContextoMusical1"
              connectionString="Data Source=|DataDirectory|Artistas.sqlite"
              providerName="System.Data.SQLite" />
      </connectionStrings>

    Desde ya, gracias!

    domingo, 6 de julio de 2014 13:28
  • cambia la configuración a

    <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" />
         </providers>
       </entityFramework>
       
       <system.data>
         <DbProviderFactories>
           <!--<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>
    
       <connectionStrings>
         <add name="ContextoMusical1"
               connectionString="Data Source=|DataDirectory|Artistas.sqlite"
               providerName="System.Data.SQLite" />
       </connectionStrings>


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos


    domingo, 6 de julio de 2014 14:19
  • si eso no te funciona, en tu config que has escrito cambia el connection string informamdondel.proveedor correcto

    <add name="ContextoMusical1"
               connectionString="Data Source=|DataDirectory|Artistas.sqlite"
               providerName="System.Data.SQLite.EF6" />

    el que acabas en .EF6


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos


    domingo, 6 de julio de 2014 14:25
  • hola

    Sqlite with Entity Framework Code First and Migration

    pero estas agregando la referencia a la libreria de sqllite que es compatible con EF6 ?

    imagen

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    domingo, 6 de julio de 2014 14:44
  • Gracias por la pronta respuesta, deje así la configuración:

     <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.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
          <!--<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.SQLiteProviderServices, System.Data.SQLite.Linq" />-->
        </providers>
      </entityFramework>
      
      <system.data>
        <DbProviderFactories>
          <!--<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" />-->
          <!--<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>
    
      <connectionStrings>
        <add name="ContextoMusical1"
              connectionString="Data Source=|DataDirectory|\Artistas.sqlite"
              providerName="System.Data.SQLite.EF6" />
      </connectionStrings>

    Deje todo con EF6.

    Ahora el error, al intentar hacer el contexto.saveChanges() es el siguiente, de tipo DbUpdateException: 

    SQL logic error or missing database no such table: Artist

    El nombre en la BD existe y está escrito de esa manera.

    Agradecería cualquier nueva sugerencia!

    Gracias!.

    domingo, 6 de julio de 2014 14:58
  • según el código que msotraste

    using (var db = new ContextoMusical1())
    {
           Artist artista = new Artist();
           artista.Name = nombreArtista;
    
            db.Artists.Add(artista); //ERROR EN TIEMPO DE EJECUCION
    
           db.SaveChanges();
    }

    Tu contexto hace referencia a Artists...

    Para ello se debería eliminar la opción de "pluralizar" los nombres de las tablas

    en tu contexto agrega

    public class ContextMusical1 : DbContext
     {
      public DbSet<Artist> Artists { get; set; }
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
      }
     }


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos

    domingo, 6 de julio de 2014 15:07
  • hola

    la base de datos la estas creando tu mismo, o dejas que EF la cree ?

    si usas una db existente podrias indicar cual es el nombre de la tabla, esto lo realizas en el mapping de la entidad

    public class ArtistMap : EntityTypeConfiguration<Artist>
    {
    	public ArtistMap()
    	{
    		ToTable("Artist");
    		 
    		//resto del mapping
    	 
    	}
    }

    valida que en la db exista esta tabla

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    domingo, 6 de julio de 2014 15:25
  • Gracias por la respuesta, pero sigue sin funcionar.

    Copio el código del contexto:

    public class ContextoMusical1 : DbContext
        {
            public ContextoMusical1()
            {
                Database.SetInitializer<ContextoMusical1>(null);
            }
    
            public DbSet<Album> Albums { get; set; }
            public DbSet<Artist> Artists { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }
        }

    Entidades:

    public class Album
        {
            public long AlbumId { get; set; }
            public string Title { get; set; }
    
            public long ArtistId { get; set; }
            public virtual Artist Artist { get; set; }
        }
    
     public class Artist
        {
            public Artist()
            {
                Albums = new List<Album>();
            }
    
            public long ArtistId { get; set; }
            
            public string Name { get; set; }
    
            public virtual ICollection<Album> Albums { get; set; }
        }

    Tablas:

    Tablas

    Configuración del archivo .sqlite

    conf sqlite

    Bueno, hasta el momento no pinchó, guardo.
    Pero sigue existiendo un problema: "No se donde está guardando".

    Verifique en el explorador de servidores la instancia de LocalDb e SQLExpress y no ha creado ninguna BD con ningún nombre de convención namespace.... o otro nombre. Y cuando quiere verificar en Firefox con el plugin SQLite Manager, sobre la tabla Artist no devuelve ningún registro, intente refrescar la bd, pero sigo sin resultados, o especificamente sin saber donde está guardando..

    Gracias por su colaboración!

    domingo, 6 de julio de 2014 15:46
  • hola

    como defines el mapping de la entidad ?

    si quieres controlarlo no se lo dejes a EF, define el ToTable()

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    domingo, 6 de julio de 2014 15:55
  • en tu carpeta bin\debug existe tu bbdd??

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos

    domingo, 6 de julio de 2014 16:01
  • Gracias por responder Leandro, pero mapeando la entidad y especificando el nombre de la tabla:

    public class MapeoArtist : EntityTypeConfiguration<Artist>
        {
            public MapeoArtist()
            {
                ToTable("Artist");
            }
        }


    No le gusta y explota, el error es el siguiente: 
    A configuration for type 'ConsoleApplication1.Entidades.Artist' has already been added. To reference the existing configuration use the Entity<T>() or ComplexType<T>() methods.

    En el tiempo de ejecución al querer hacer el Add de un objecto a una entidad del contexto.

    domingo, 6 de julio de 2014 16:13
  • Si está 

    Si está.
    Aclara que estoy usando las versiones que provee desde Nuget de EF 6 y de System.Data.SQLite (salió hace 2 semanas).

    Gracias nuevamente a todos!

    domingo, 6 de julio de 2014 16:17
  • Si accedes a dicho archivo de bbdd que se encuentra en bin\debug el registro que has añadido existe en dicha bbdd?

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó vótala como útil. Saludos

    domingo, 6 de julio de 2014 16:21
  • No existe, está vacia la tabla.

    Por lo tanto depure el código al insertar.

    string nombreArtista = String.Empty;
    
                while (nombreArtista != "0")
                {
                    Console.WriteLine("Ingresar el nombre un artista (0 para Salir):");
                    nombreArtista = Console.ReadLine().Trim();
                    if (nombreArtista != "0")
                    {
                        using (var db = new ContextoMusical1())
                        {
                            Artist artista = new Artist();
                            artista.Name = nombreArtista;
    
                            db.Artists.Add(artista);
    
                            db.SaveChanges();
                        }
                    }
                }
    
                //Obtengo todos los artistas y los listo
    
                using (var db = new ContextoMusical1())
                {
                    var rv = db.Artists.Select(a => a.Name).ToList();
    
                    foreach (var item in rv)
                    {
                        Console.WriteLine(item);
                        Console.WriteLine();
                    }
                }

    Si mantenía la hipótesis de que en una ejecución anterior, había pasado el contexto.saveChanges() y no explotó, y asumí que había insertado, "pero no sabía donde". Entonces al ejecutar nuevamente la aplicación e insertar un nuevo elemento, al listar "todos los elementos" debería traerme 2, pero lamentablemente trajo 1, el de la ejecución actual.

    Por lo tanto pienso que está funcionando en memoria la BD, y como que no de forma física o almacenándolo físicamente..


    domingo, 6 de julio de 2014 17:34
  • Gracias a todos por la ayuda y la persistencia!.

    Volví a crear un nuevo proyecto de consola desde 0, la idea era una entidad con 2 propiedades y 1 sola tabla.

    Paso a describir con detalle la metodología y versiones de archivos utilizados:

    1 Una vez creado el proyecto de consola cree la siguiente entidad:

    public class Artista
        {
            public Int64 ArtistaId { get; set; }
            public string Nombre { get; set; }
        }


    Instalé EF 6 con Nuget sobre el proyecto de consola (versión 6.1.1)

    Cree la clase de contexto:

    public class ContextoArtista : DbContext
        {
            public DbSet<Artista> Artistas { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    
                base.OnModelCreating(modelBuilder);
            }
        }


    Hasta el momento en App.Config tenemos:

    <?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>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>


    Sobre el proyecto, a través de Nuget instalamos el siguiente paquete (System.Data.SQLite (x86/x64))  que a su vez automáticamente instala las referencias necesarias.

    Para la administración de la BD SQLite utilize un plugin de Firefox llamado SQLite Manager:

    Entonces cree la tabla con las 2 columnas, y la carpeta de destino fue Visual Studio 2012\Projects\SQLiteBasico\ConsoleApplication\bin\Debug donde se alojara el archivo .sqlite.

    Luego agregué el archivo al proyecto, como "agregar elemento existente". No configure nada en sus propiedades (click derecho /propiedades sobre el archivo .sqlite agregado al proyecto).

    Lo próximo fue ver como estaba App.Config y modificarlo (luego de agregar los paquetes de SQLite cambió):

    <?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>
        <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.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
        </providers>
      </entityFramework>
      
      <system.data>
        <DbProviderFactories>
          <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" />
          <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>
      
    </configuration>

    Por defecto en System.data, en el 1er remove, hay que modificar agregando la extension .EF6

    <DbProviderFactories>
          <remove invariant="System.Data.SQLite.EF6" />

    Tmbién en el 1er add

     <add name="SQLite Data Provider" invariant="System.Data.SQLite.EF6" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />

    Luego agregar una connectionString:

     <connectionStrings>
        <add name="ContextoArtista"
              connectionString="Data Source=|DataDirectory|artistas.sqlite"
              providerName="System.Data.SQLite.EF6" />
      </connectionStrings>
      

    Resumiendo, el app.config quedó:

    <?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>
        <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.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
        </providers>
      </entityFramework>
      
      <system.data>
        <DbProviderFactories>
          <remove invariant="System.Data.SQLite.EF6" />
          <add name="SQLite Data Provider" invariant="System.Data.SQLite.EF6" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
          <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>
    
      <connectionStrings>
        <add name="ContextoArtista"
              connectionString="Data Source=|DataDirectory|artistas.sqlite"
              providerName="System.Data.SQLite.EF6" />
      </connectionStrings>
      
    </configuration>

    Por último el código de prueba:

    class Program
        {
            static void Main(string[] args)
            {
                string nombreArtista = String.Empty;
    
                while (nombreArtista != "0")
                {
                    Console.WriteLine("Ingresar el nombre un artista (0 para Salir):");
                    nombreArtista = Console.ReadLine().Trim();
                    if (nombreArtista != "0")
                    {
                        using (var db = new ContextoArtista())
                        {
                            Artista artista = new Artista();
                            artista.Nombre = nombreArtista;
    
                            db.Artistas.Add(artista);
    
                            db.SaveChanges();
                        }
                    }
                }
    
                //Obtengo todos los artistas y los listo
    
                using (var db = new ContextoArtista())
                {
                    var rv = db.Artistas.Select(a => a.Nombre).ToList();
    
                    foreach (var item in rv)
                    {
                        Console.WriteLine(item);
                        Console.WriteLine();
                    }
                }
                Console.WriteLine();
            }
        }

    Espero que le sirva a algún miembro que llegue con las mismas dudas y/o problemas

    Ante todo gracias a Leandro y Sergio.

    domingo, 6 de julio de 2014 19:11