EF Core, Sqlite, InMemory, сначала код — как?

#c# #sqlite #entity-framework-core

#c# #sqlite #сущность-фреймворк-ядро

Вопрос:

Я хочу создать базу данных со структурой из моей тестовой модели. В памяти. Использование Sqlite и Entity Framework Core. Конечно, сначала код. Я создал свою модель.

DataDataContext.cs:

 using Microsoft.EntityFrameworkCore;

namespace MyTest.Data {

    public class DataContext : DbContext {

        public DbSet<Record> Records { get; set; }

        public DataContext(DbContextOptions options) : base(options) { }

    }

}
  

DataRecord.cs:

 using System;

namespace MyTest.Data {

    public class Record {

        public int Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public DateTime Time { get; set; }

    }
}
  

И у меня есть этот тестовый код:

 using System;
using System.Data.Common;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

using MyTest.Data;

namespace MyTest {
    
    public class Startup {
        
        static DbConnection TestDbConnection = new SqliteConnection("Data Source=:memory:;Cache=shared");

        void InitializeTestDatabase() {
            var dbOptions = new DbContextOptionsBuilder().UseSqlite(TestDbConnection).Options;
            var dbContext = new DataContext(dbOptions);
            dbContext.Database.EnsureCreated();
            for (int i = 0; i < 1024; i  ) {
                var testString = Guid.NewGuid().ToString();
                dbContext.Records.Add(new Record { Name = testString.Substring(0, 8), Description = testString, Time = DateTime.Now });
            }
            dbContext.SaveChanges();
        }

    }

}
  

Конечно, это вызывает исключение SQL, потому что нет такой таблицы, как «Записи». Очевидно. Структура обычно создавалась с помощью миграций, но я читал, что вы не можете использовать миграции InMemory . Что я должен использовать EnsureCreated() вместо этого. Но тогда как я могу получить структуру, построенную из кода моей модели? Чего мне здесь не хватает?

Комментарии:

1. Зачем вам нужно использовать InMemory? предполагается, что in-mem не является устойчивой базой данных, поэтому нет смысла использовать миграции, которые являются средством для разумного и прокручиваемого во времени развития производственной базы данных с течением времени. Я считаю, что EnsureCreated должен создать БД, совместимую с моделью, и (поскольку она также не создает БД, которая функционирует при миграции) соответствует целям in-mem, но я не уверен, что in-mem — это то, что вы в конечном итоге захотите сделать. Таким образом, вам, возможно, следует подумать о создании базы данных обычным способом, на диске, с использованием миграции (больше времени на разработку, чем на выполнение)

2. @CaiusJard Я просто хочу создать тестовую таблицу. Фиктивная таблица в фиктивной базе данных для тестирования, но я хочу сделать ее как можно более простой (нулевая конфигурация / зависимости / пути / ссылки на файлы). Кроме того, сначала код — поэтому я не хочу писать SQL или создавать структуру базы данных иначе — EF может сделать это за меня, не так ли? Все, что меня волнует, это иметь таблицу с данными. Создается при каждом запуске приложения. Мне не нужны файлы, я не хочу создавать таблицу вручную.

Ответ №1:

Мне нужно было добавить SqliteConnection.Open вызов в мое соединение, чтобы оно заработало:

 var conn = new SqliteConnection("DataSource=:memory:");
conn.Open(); // open connection to use

var options = new DbContextOptionsBuilder<VegaDbContext>()
   .UseSqlite(conn)
   .Options;

using (var ctx = new VegaDbContext(options))
{
    ctx.Database.EnsureCreated();
    ctx.Records.ToList();
}
  

Комментарии:

1. Удивительно, сообщение об ошибке, которое я получал, тогда вводило в заблуждение. В нем говорилось, что у меня нет таблицы Records , но открытие соединения перед его использованием в моем контексте данных решило проблему. Я скептически отнесся к этой идее, но я протестировал ее, и она действительно работает. Большое спасибо!

2. @Harry был рад помочь! У меня была та же таблица и та же проблема)

3. Это задокументировано, просто кто-то должен его прочитать — с использованием баз данных SQLite в памяти .

4. @IvanStoev Я прочитал это первым, но я все равно забыл об открытии соединения. Мой плохой. Что там происходит? EnsureCreated() Создает ли структура базы данных, если соединение открыто, и молча пропускает это, когда оно закрыто? Мне просто любопытно.

5. EnsureCreated опирается на два абстрактных метода bool Exists() и bool HasTables() . Они реализованы каждым поставщиком баз данных. Реализация Sqlite находится в классе, SqliteDatabaseCreator который вы можете найти в репозитории GitHub ядра EF. Exists Метод начинается с if (connectionStringBuilder.DataSource.Equals(":memory:", StringComparison.OrdinalIgnoreCase) || connectionStringBuilder.Mode == SqliteOpenMode.Memory) return true; 🙂