Как Создать Таблицу с Ключом Enum в EF?
Допустим, у нас есть сущность с ограниченным количеством типов сущности, которые редко, но могут добавляться. Для лучшей читаемости кода мы хотели бы использовать enum для типов сущности, при этом имея полноценную таблицу в БД, где каждому значению enum соответствовала бы строка с дополнительной информацией. Также желательно, чтобы при добавлении значения в enum, у нас в БД появлялась новая строка.
Для этого мы можем использовать комбинацию двух функций EF Core:
- Преобразование значений — для преобразования перечисления в int при чтении/записи в БД.
- Присвоение начальных значений данных — для добавления значений перечисления в базу данных при миграции.
Допустим, мы создаём систему для винного магазина. У нас есть вина и их виды:
public enum WineTypeТогда в файле контекста WineContext в методе OnModelCreating нам нужно настроить преобразование значений (enum в int):
{
Red = 1,
White = 2
}
public class Wine
{
public int Id { get; set; }
public string Name { get; set; }
public WineType Type { get; set; }
public WineTypeDetails TypeDetails { get; set; }
}
public class WineTypeDetails
{
public WineType Type { get; set; }
public string Name { get; set; }
public List<Wine>? Wines { get; set; }
}
protected override void OnModelCreating(ModelBuilder mb)И присвоение начальных значений (таблица типов заполняется из enum):
{
mb.Entity<Wine>()
.Property(w => w.Type)
.HasConversion<int>();
mb.Entity<WineTypeDetails>()
.Property(t => t.Type)
.HasConversion<int>();
mb.Entity<WineTypeDetails>()
.HasKey(t => t.Type);
…
mb.Entity<WineTypeDetails>().HasData(Теперь используем это в программе:
Enum.GetValues(typeof(WineType))
.Cast<WineType>()
.Select(t => new WineTypeDetails() {
Type = t,
Name = t.ToString()
})
);
}
using Microsoft.EntityFrameworkCore;Вывод:
using (var db = new WineContext())
{
await db.Database.MigrateAsync();
if (!db.Wines.Any())
{
db.Wines.Add(new Wine
{
Name = "Saperavi",
Type = WineType.Red,
});
db.Wines.Add(new Wine
{
Name = "Cabernet",
Type = WineType.Red,
});
db.Wines.Add(new Wine
{
Name = "Chardonnay",
Type = WineType.White,
});
}
await db.SaveChangesAsync();
}
using (var db = new WineContext())
{
var types = await db.WineTypes
.ToListAsync();
foreach (var type in types)
{
Console.WriteLine($"{type.Name} wines:");
var wines = await db.Wines
.Include(w => w.TypeDetails)
.Where(w => w.Type == type.Type)
.ToListAsync();
foreach (var wine in wines)
Console.WriteLine($"{wine.Name} is
a {wine.TypeDetails.Name} wine");
}
}
Red wines:Теперь мы можем добавить значение в enum, например, Rose, и добавить новую миграцию. Соответствующая строка будет добавлена в таблицу WineTypeDetails автоматически. При этом существующие строки при миграциях изменяться не будут. Кроме того, в таблицу типов можно добавить и другие столбцы, например, Description.
Saperavi is a Red wine
Cabernet is a Red wine
White wines:
Chardonnay is a White wine
Полный код примера тут.
Источник: https://stackoverflow.com/questions/50375357/how-to-create-a-table-corresponding-to-enum-in-ef-core-code-first