Иногда необходимо, чтобы при первом обращении база данных уже содержала некоторые данные. И Entity Framework Core позволяет инициализировать базу данных при ее создании некоторыми начальными данными. Благодаря этому к моменту первого использования базы данных она уже будет содержать начальные данные, которые мы сможем тут же использовать. И нам не потребуется вручную или программно добавлять в БД нужные нам данные.
Для инициализации БД при конфигурации определенной модели вызывается метод HasData(), в который передаются добавляемые данные:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasData( new User { Id=1, Name="Tom", Age=36}); }
Например, инициализируем БД набором данных:
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasData( new User { Id = 1, Name = "Tom", Age = 23 }, new User { Id = 2, Name = "Alice", Age = 26 }, new User { Id = 3, Name = "Sam", Age = 28 } ); } } public class User { public int Id { get; set; } public string? Name { get; set; } public int Age { get; set; } }
У объекта ModelBuilder, который передается в OnModelCreating в качестве параметра, вызывается метод Entity<T>(). Этот метод типизируется типом, для которого будут добавляться начальные данные. То есть в данном случае данные будут добавляться в таблицу, где хранятся объекты User. Поэтому Entity типизируется типом User.
Далее по цепочке вызывается метод HasData(), который собственно и определяет начальные данные. В данном случае это набор из трех объектов User. При этом для каждого объекта необходимо установить значение первичного ключа - в данном случае значение свойства Id. Причем вне зависимости, генерирует ли база данных для данных автоматически индентификатор или нет, нам в любом случае его надо установить - это основное ограничение при инициализации БД начальными данными.
При этом следует учитывать, что инициализация начальными данными будет выполняться только в двух случаях:
При выполнении миграции. (При создании миграции добавляемые данные автоматически включаются в скрипт миграции)
При вызове метода Database.EnsureCreated(), который создает БД при ее отсутствии
В случае выше в конструкторе применяется метод Database.EnsureCreated(), поэтому при создании контекста данных
ApplicationContext db = new ApplicationContext();
будет автоматически производиться инициализация бд начальными данными.
Аналогично можно инициализировать данные нескольких сущностей, в том числе связанных между собой:
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public DbSet<Company> Companies { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp1.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { // определяем компании Company microsoft = new Company { Id = 1, Name = "Microsoft" }; Company google = new Company { Id = 2, Name = "Google" }; // определяем пользователей User tom = new User { Id = 1, Name = "Tom", Age = 23, CompanyId = microsoft.Id }; User alice = new User { Id = 2, Name = "Alice", Age = 26, CompanyId = microsoft.Id }; User sam = new User { Id = 3, Name = "Sam", Age = 28, CompanyId = google.Id }; // добавляем данные для обеих сущностей modelBuilder.Entity<Company>().HasData(microsoft, google); modelBuilder.Entity<User>().HasData(tom, alice, sam); } } public class User { public int Id { get; set; } public string? Name { get; set; } public int Age { get; set; } public Company? Company { get; set; } public int? CompanyId { get; set; } } public class Company { public int Id { get; set; } public string? Name { get; set; } public List<User> Users { get; set; } = new(); }