TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #2064 2.01K
День 1699. #ЗаметкиНаПолях
Как Создать Таблицу с Ключом Enum в EF?
Допустим, у нас есть сущность с ограниченным количеством типов сущности, которые редко, но могут добавляться. Для лучшей читаемости кода мы хотели бы использовать enum для типов сущности, при этом имея полноценную таблицу в БД, где каждому значению enum соответствовала бы строка с дополнительной информацией. Также желательно, чтобы при добавлении значения в enum, у нас в БД появлялась новая строка.

Для этого мы можем использовать комбинацию двух функций EF Core:
- Преобразование значений — для преобразования перечисления в int при чтении/записи в БД.
- Присвоение начальных значений данных — для добавления значений перечисления в базу данных при миграции.

Допустим, мы создаём систему для винного магазина. У нас есть вина и их виды:
public enum WineType
{
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; }
}

Тогда в файле контекста WineContext в методе OnModelCreating нам нужно настроить преобразование значений (enum в int):
protected override void OnModelCreating(ModelBuilder mb)
{
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);
…

И присвоение начальных значений (таблица типов заполняется из enum):
  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:
Saperavi is a Red wine
Cabernet is a Red wine
White wines:
Chardonnay is a White wine

Теперь мы можем добавить значение в enum, например, Rose, и добавить новую миграцию. Соответствующая строка будет добавлена в таблицу WineTypeDetails автоматически. При этом существующие строки при миграциях изменяться не будут. Кроме того, в таблицу типов можно добавить и другие столбцы, например, Description.
Полный код примера тут.

Источник: https://stackoverflow.com/questions/50375357/how-to-create-a-table-corresponding-to-enum-in-ef-core-code-first
  • 👍 26
More from @netdeveloperdiary
  1. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  2. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  3. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  4. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  5. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  6. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →