SQLite + EF: создать БД файл на лету по модели.
От: Uzzy Россия  
Дата: 13.09.15 19:03
Оценка:
Убил прилично часов на изыскания пути / возможности / реализации создания SQLite. Задача была такая — были классы-модели типа

public class A1
{
   public int Key {get;set;} 
   public string Name {get;set;} 
}


был путь к БД файлу. Если файла нет — надо бы создать (ну случай инсталяции на клиента например) с помощью EF. Изыскания в интернетах отправляли в частности к sqlite.net который в целом то умел, но мне не помог, от слова совсем. Много раз в том stackoverflow либо отправляли вопрощающих к sqlite.net либо говорили, мол не получится. Либо я разучился искать в интернетах.

В конечном итоге получилось с помощью двух nuget-package: System.Data.SQLite (который тянет с собой в том числе и EF) и SQLite.CodeFirst.

для реализации в DBContext-е потребовалось написать следующие (здесь используются фишки SQLite.CodeFirst)
   public sealed class SampleDbContext : DbContext
   {
      public SampleDbContext(SQLiteConnection sqLiteConnection)
         : base(sqLiteConnection, false)
      {
      }

      public DbSet<A1> A1{ get; set; }

      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
         var initializer =
            new SQLite.CodeFirst.SqliteDropCreateDatabaseAlways<SampleDbContext>(modelBuilder);
         Database.SetInitializer(initializer);

         base.OnModelCreating(modelBuilder);
      }
   }


и собственно создания базы
      public void CreateDatabaseFile(string path)
      {
         try
         {
            using (SQLiteConnection sqLiteConnection = CreateConnection(path))
            using (SampleDbContext context = new SampleDbContext(sqLiteConnection))
            {
               DropCreateDatabaseAlways<SampleDbContext> initializator =
                  new DropCreateDatabaseAlways<SampleDbContext>();
               Database.SetInitializer(initializator);

               context.SaveChanges();
               // do not delete this log trace. we need some DB touch
               _log.Trace("Db Context validated. Found {0} Customer(s)", context.A1.Count());
            }
         }
         catch (Exception ex)
         {
            _log.Error(ex);
         }
      }

      public static SQLiteConnection CreateConnection(string path)
      {
         SQLiteConnectionStringBuilder builder =
            (SQLiteConnectionStringBuilder) SQLiteProviderFactory.Instance.CreateConnectionStringBuilder();
         builder.DataSource = path;
         builder.FailIfMissing = false;

         return new SQLiteConnection(builder.ToString());
      }


И немного магии в app.config, если жирных строчек нет, добавляем руками

  <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>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v12.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <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.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>



В примерах опущены валидаторы параметров и прочее, если есть способы поэлегантнее — буду благодарен, если поделитесь таковыми. а так надеюсь мои изыскания сохранят кому-нибудь время.
Re: SQLite + EF: создать БД файл на лету по модели.
От: bnk СССР http://unmanagedvisio.com/
Дата: 13.09.15 23:10
Оценка: 12 (2)
Здравствуйте, Uzzy, Вы писали:

U>Убил прилично часов на изыскания пути / возможности / реализации создания SQLite. Задача была такая — были классы-модели типа


Мелкомягкие же только в EF7 обещают SqLite из коробки? В принципе вроде все как-то работает.

@> Install-Package EntityFramework.SqLite -Pre
@> Install-Package EntityFramework.Commands -Pre

using Microsoft.Data.Entity;

namespace ConsoleApplication1
{
    public class Test
    {
        public int id { get; set; }
        public string name { get; set; }
    }

    public class AppContext : DbContext
    {
        public DbSet<Test> Test { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite(@"Data Source=C:\Projects\<yourpath>\db.sqlite");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var context = new AppContext();
            context.Database.Migrate();
        }
    }
}


@> Add-Migration Init

F5
Отредактировано 13.09.2015 23:12 bnk . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.