0Pricing
C# Academy · Урок

Основы DbContext и DbSet

Настройте DbContext, определите сущности, задайте строку подключения и выполните свой первый запрос.

«Основы DbContext и DbSet» — бесплатный урок C# Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Что такое Entity Framework Core

EF Core — официальный объектно-реляционный преобразователь (ORM) для .NET. Он сопоставляет классы C# (сущности) с таблицами базы данных и позволяет запрашивать и сохранять данные с помощью LINQ — для большинства операций SQL не требуется.

Определение сущности

Сущность — это обычный класс C#, свойства которого сопоставляются со столбцами базы данных. По соглашению свойство с именем Id или <TypeName>Id становится первичным ключом.

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public int Stock { get; set; }
    public DateTime CreatedAt { get; set; }
}

Создание DbContext

DbContext — это точка доступа к базе данных. Он содержит свойства DbSet<T> для каждой сущности и управляет подключением, отслеживанием изменений и транзакциями.

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options) { }

    public DbSet<Product> Products => Set<Product>();
    public DbSet<Order>   Orders   => Set<Order>();
}

Регистрация DbContext в DI

Вызовите AddDbContext в Program.cs, чтобы зарегистрировать контекст как сервис с временем жизни Scoped и настроить поставщика базы данных.

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("Default")));

// For SQLite (great for development/testing):
// options.UseSqlite("Data Source=app.db");

Базовые запросы с DbSet

DbSet<T> предоставляет операторы LINQ. Запросы не выполняются, пока их результаты не будут перечислены (await ...ToListAsync()). Это называется отложенным выполнением.

public class ProductService
{
    private readonly AppDbContext _db;
    public ProductService(AppDbContext db) => _db = db;

    public async Task<List<Product>> GetExpensiveAsync(decimal minPrice)
    {
        return await _db.Products
            .Where(p => p.Price >= minPrice)
            .OrderBy(p => p.Name)
            .ToListAsync();
    }
}

Поиск по первичному ключу

FindAsync сначала проверяет локальный кэш отслеживания изменений, а уже затем обращается к базе данных. Используйте его при запросе по первичному ключу, чтобы избежать лишних обращений к базе данных.

var product = await _db.Products.FindAsync(42);
if (product is null)
    throw new KeyNotFoundException("Product not found");

// For complex keys, pass all key values:
var orderLine = await _db.OrderLines.FindAsync(orderId, productId);

Добавление новых записей

Вызовите Add, чтобы поставить сущность в очередь на добавление, а затем вызовите SaveChangesAsync для фиксации изменений. EF Core генерирует SQL-оператор INSERT и заполняет автоматически сгенерированный Id.

var product = new Product
{
    Name = "Mechanical Keyboard",
    Price = 149.99m,
    Stock = 50,
    CreatedAt = DateTime.UtcNow
};

_db.Products.Add(product);
await _db.SaveChangesAsync();

Console.WriteLine(product.Id); // Auto-generated PK

Обновление записей

Сущности, загруженные EF Core, отслеживаются. Изменяйте свойства напрямую и вызывайте SaveChangesAsync — EF Core обнаружит изменения и сгенерирует оптимизированный оператор UPDATE.

var product = await _db.Products.FindAsync(42);
if (product is not null)
{
    product.Price = 129.99m;
    product.Stock -= 1;
    await _db.SaveChangesAsync(); // UPDATE Products SET Price=...
}

Удаление записей

Вызовите Remove, чтобы пометить сущность на удаление, а затем вызовите SaveChangesAsync. Используйте ExecuteDeleteAsync (начиная с .NET 7) для массового удаления без загрузки сущностей.

// Delete a tracked entity
_db.Products.Remove(product);
await _db.SaveChangesAsync();

// Bulk delete without loading (EF Core 7+)
await _db.Products
    .Where(p => p.Stock == 0)
    .ExecuteDeleteAsync();

Настройка с помощью Fluent API

Переопределите OnModelCreating, чтобы настроить сущности с помощью Fluent API: имена таблиц, типы столбцов, ограничения, индексы и связи.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>(entity =>
    {
        entity.ToTable("products");
        entity.Property(p => p.Name).IsRequired().HasMaxLength(200);
        entity.Property(p => p.Price).HasColumnType("decimal(18,2)");
        entity.HasIndex(p => p.Name);
    });
}

Практика: репозиторий на основе DbContext

Типичный репозиторий оборачивает DbContext, чтобы централизовать логику доступа к данным и скрыть детали запросов от классов сервисов.

public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _db;
    public ProductRepository(AppDbContext db) => _db = db;

    public async Task<Product?> GetByIdAsync(int id)
        => await _db.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == id);

    public async Task<List<Product>> SearchAsync(string query)
        => await _db.Products
            .Where(p => p.Name.Contains(query))
            .AsNoTracking()
            .ToListAsync();
}

Быстрая проверка

Что делает AsNoTracking() при выполнении запроса с EF Core?

Итоги: основы DbContext и DbSet

Главное:

  • DbContext — это сеанс работы с базой данных; DbSet<T> представляет таблицу
  • Зарегистрируйте его с помощью AddDbContext в DI; по умолчанию он имеет время жизни Scoped
  • Запросы LINQ выполняются отложенно — запустите их с помощью ToListAsync или FirstOrDefaultAsync
  • Отслеживание изменений позволяет автоматически выполнять UPDATE/DELETE через SaveChangesAsync
  • Используйте AsNoTracking() для запросов только на чтение, чтобы повысить производительность

Часто задаваемые вопросы

Урок «Основы DbContext и DbSet» бесплатный?

Да — полный текст урока «Основы DbContext и DbSet» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Основы DbContext и DbSet»?

Настройте DbContext, определите сущности, задайте строку подключения и выполните свой первый запрос. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Основы DbContext и DbSet»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы DbContext и DbSet
  2. Миграции и управление схемой
  3. Операции CRUD с EF Core
  4. Связи: один-ко-многим и многие-ко-многим
← Назад к C# Academy