Entity Framework Core (EF Core) — это мощный, легковесный и кроссплатформенный ORM (Object-Relational Mapper) от Microsoft, который стал незаменимым инструментом для .NET разработчиков. Он позволяет работать с базами данных, используя знакомые объекты C#, вместо написания громоздкого SQL-кода. В этой статье мы разберем практические примеры, от простых CRUD-операций до сложных сценариев, которые помогут вам уверенно интегрировать EF Core в свои проекты.
Основы: создание модели и контекста данных
Вся работа начинается с определения сущностей (моделей) и контекста данных (DbContext). DbContext — это сердце EF Core, он управляет подключением к базе данных, отслеживанием изменений и сохранением данных.
public class Blog
{
public int Id { get; set; } // Первичный ключ
public string Title { get; set; }
public string Content { get; set; }
public DateTime CreatedAt { get; set; }
// Навигационное свойство (один ко многим)
public ICollection Comments { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Author { get; set; }
public string Text { get; set; }
public int BlogId { get; set; } // Внешний ключ
// Навигационное свойство (многие к одному)
public Blog Blog { get; set; }
}
public class ApplicationDbContext : DbContext
{
public DbSet Blogs { get; set; }
public DbSet Comments { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Пример для SQL Server
optionsBuilder.UseSqlServer(@"Server=(localdb)\\mssqllocaldb;Database=BlogDb;Trusted_Connection=True;");
}
}
Используйте подход Code-First: сначала создавайте классы C#, а EF Core сгенерирует или обновит схему базы данных с помощью миграций. Это делает процесс разработки более гибким и контролируемым.
CRUD-операции: создание, чтение, обновление, удаление
Давайте рассмотрим базовые операции с данными.
Добавление данных (Create)
using (var context = new ApplicationDbContext())
{
var blog = new Blog
{
Title = "Мой первый блог",
Content = "Содержание...",
CreatedAt = DateTime.Now
};
context.Blogs.Add(blog); // или await context.Blogs.AddAsync(blog);
context.SaveChanges(); // Фиксация изменений в БД
}
Запрос данных (Read) с LINQ
EF Core тесно интегрирован с LINQ (Language Integrated Query).
// Получить все блоги
var allBlogs = context.Blogs.ToList();
// Получить блог по ID
var blog = context.Blogs.Find(1);
// Фильтрация и сортировка
var recentBlogs = context.Blogs
.Where(b => b.CreatedAt > DateTime.Now.AddDays(-7))
.OrderByDescending(b => b.CreatedAt)
.ToList();
// Жадная загрузка связанных данных (Eager Loading)
var blogsWithComments = context.Blogs
.Include(b => b.Comments) // Загружаем комментарии сразу
.ToList();
Обновление (Update) и удаление (Delete)
// Обновление
var blogToUpdate = context.Blogs.Find(1);
if (blogToUpdate != null)
{
blogToUpdate.Title = "Обновленный заголовок";
context.SaveChanges();
}
// Удаление
var blogToDelete = context.Blogs.Find(2);
if (blogToDelete != null)
{
context.Blogs.Remove(blogToDelete);
context.SaveChanges();
}
Продвинутые сценарии и лучшие практики
Миграции (Migrations)
Миграции — это система контроля версий для схемы вашей базы данных. После изменения моделей выполните в консоли диспетчера пакетов (Package Manager Console):
Add-Migration InitialCreate // Создает миграцию
Update-Database // Применяет миграцию к БД
Fluent API для тонкой настройки
Помимо атрибутов (например, [Key], [Required]), вы можете использовать Fluent API в методе OnModelCreating для более детальной конфигурации.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Title)
.IsRequired()
.HasMaxLength(200);
modelBuilder.Entity()
.HasMany(b => b.Comments)
.WithOne(c => c.Blog)
.HasForeignKey(c => c.BlogId)
.OnDelete(DeleteBehavior.Cascade); // Каскадное удаление
}
Для повышения производительности в веб-приложениях всегда используйте асинхронные методы (ToListAsync(), SaveChangesAsync()) и старайтесь не загружать избыточные данные. Используйте проекции (.Select()) для получения только необходимых полей.
Работа с транзакциями
using (var transaction = context.Database.BeginTransaction())
{
try
{
// Несколько операций с БД
context.Blogs.Add(newBlog);
context.Comments.AddRange(newComments);
context.SaveChanges();
transaction.Commit(); // Подтверждаем изменения
}
catch
{
transaction.Rollback(); // Откатываем в случае ошибки
throw;
}
}
FAQ: Часто задаваемые вопросы о Entity Framework Core
В чем разница между EF Core и EF6?
EF Core — это переписанная с нуля, кроссплатформенная и более легковесная версия. EF6 — это зрелый, но исключительно .NET Framework ORM с несколько большей функциональностью для сложных сценариев.
Как выбрать стратегию загрузки связанных данных?
- Eager Loading (Жадная) (.Include()): Данные загружаются сразу одним запросом. Используйте, когда заранее знаете, что связанные данные понадобятся.
- Explicit Loading (Явная) (.Load()): Данные загружаются отдельным запросом по требованию.
- Lazy Loading (Ленивая): Данные загружаются автоматически при обращении к навигационному свойству. Требует установки отдельного пакета и виртуальных свойств.
Как улучшить производительность EF Core?
- Используйте асинхронные методы.
- Применяйте проекции (.Select()) вместо загрузки полных сущностей.
- Отключайте отслеживание изменений (.AsNoTracking()) для запросов "только для чтения".
- Правильно настраивайте индексы в базе данных через Fluent API или миграции.
- Избегайте N+1 проблемы запросов (когда в цикле выполняются дополнительные запросы к БД).
Поддерживает ли EF Core NoSQL базы данных?
Да, через сторонние провайдеры. Официально Microsoft предоставляет провайдеры для реляционных БД (SQL Server, SQLite, PostgreSQL и др.). Для работы с Cosmos DB (NoSQL от Microsoft) также существует официальный провайдер EF Core.