Назад к вопросам
Middle
119
questionbank

Как работает Entity Framework?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Entity Framework (EF) — это ORM (Object-Relational Mapper) для .NET. Он позволяет работать с базами данных, используя доменные объекты .NET, избавляя от необходимости написания большей части кода для доступа к данным.

Принципы работы:

  1. Маппинг: EF устанавливает соответствие между классами C# и таблицами базы данных, а также между свойствами классов и столбцами таблиц.
  2. LINQ to Entities: Позволяет писать запросы к данным на привычном LINQ, который EF преобразует в SQL-запросы для выполнения в базе данных.
  3. DataContext / DbContext: Основной класс, представляющий сессию взаимодействия с базой данных. Отслеживает изменения объектов, выполняет запросы и сохраняет изменения.
  4. Отслеживание изменений: EF отслеживает состояние объектов, загруженных из базы данных (Added, Modified, Deleted, Unchanged, Detached).
  5. Генерация SQL: На основе LINQ-запросов и отслеживаемых изменений EF генерирует соответствующие SQL-операторы (SELECT, INSERT, UPDATE, DELETE).
  6. Выполнение команд: Сгенерированные SQL-команды отправляются в базу данных для выполнения.
  7. Маппинг результатов: Результаты выполнения SQL-запросов преобразуются обратно в доменные объекты .NET.

Рабочий процесс:

  1. Определение модели данных (POCO-классы).
  2. Создание класса, наследующего DbContext.
  3. Конфигурация соединения с базой данных.
  4. Написание LINQ-запросов для получения, добавления, изменения или удаления данных.
  5. Вызов метода SaveChanges() для сохранения отслеживаемых изменений в базе данных.

EF поддерживает два основных подхода к разработке:

  • Code-First: Модель данных определяется с помощью POCO-классов, а база данных генерируется на основе этой модели (включая миграции для обновления схемы).
  • Database-First: Модель данных генерируется на основе существующей базы данных.

Ключевые компоненты:

  • DbContext: Управляет сеансом работы с базой данных.
  • DbSet<TEntity>: Представляет коллекцию сущностей указанного типа в контексте или базе данных.
  • DbChangeTracker: Отслеживает изменения сущностей.
  • Миграции (Migrations): Средство для управления эволюцией схемы базы данных при изменении модели Code-First.
  • Поставщик данных (Database Provider): Адаптер между EF и конкретной СУБД.
// Пример использования DbContext и DbSet
public class ApplicationDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Order> Orders { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Пример конфигурации для SQL Server
        optionsBuilder.UseSqlServer("ConnectionString");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Дополнительная конфигурация модели (например, Fluent API)
        modelBuilder.Entity<Order>()
            .HasOne(o => o.User)
            .WithMany(u => u.Orders);
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public string ProductName { get; set; }
    public decimal Quantity { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
}

// Пример запроса и сохранения данных
public class DataAccess
{
    public void AddNewUser(string name)
    {
        using (var context = new ApplicationDbContext())
        {
            var newUser = new User { Name = name };
            context.Users.Add(newUser); // Добавление в DbSet, EF отслеживает состояние Added
            context.SaveChanges(); // Генерация и выполнение INSERT SQL
        }
    }

    public List<Order> GetUserOrders(int userId)
    {
        using (var context = new ApplicationDbContext())
        {
            // LINQ-запрос, будет преобразован в SELECT SQL с JOIN
            return context.Orders
                .Where(o => o.UserId == userId)
                .Include(o => o.User) // Жадная загрузка связанного объекта User
                .ToList(); // Выполнение SQL и возврат списка объектов Order
        }
    }

    public void UpdateUserName(int userId, string newName)
    {
        using (var context = new ApplicationDbContext())
        {
            var user = context.Users.Find(userId); // Загрузка пользователя, EF отслеживает состояние Unchanged
            if (user != null)
            {
                user.Name = newName; // EF обнаруживает изменение, состояние переходит в Modified
                context.SaveChanges(); // Генерация и выполнение UPDATE SQL
            }
        }
    }
}

Таблица состояний сущностей:

Состояние Описание
Added Объект добавлен в контекст, но еще не сохранен в БД.
Unchanged Объект загружен из БД и не был изменен.
Modified Объект загружен из БД и был изменен.
Deleted Объект помечен для удаления из БД.
Detached Объект не отслеживается контекстом EF.