#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;
🙂