Как Entity Framework отслеживает изменение объектов?

304
04 июня 2022, 20:50

Как Entity Framework отслеживает изменение объектов? Еще когда через методы идет вызов понятно, а как он отслеживает объект который мы получили, сделали изменение и вызвали метод сохранить? Мол по факту мы записали в свой же класс. Например:

using(UserContext db = new UserContext())
{
     db.Users.Where(w=>w.Id==3).First().Name="Ivan";
     db.SaveChanges();
}

П.С. В примере получили пользователя с Id равным 3 и поменяли ему имя. Как EF отследило изменение? И как можно сделать самому отслеживание элементов?

Answer 1

Посмотрел доку. В общем, EF просто хранит "снимок" всех объектов и потом проверяет для всех "присоединённых" объектов соответствие этому "снимку", чтобы найти изменения.

При использовании большинства сущностей POCO (plain old CLR object) определение того, каким образом изменилась сущность (и, следовательно, какие обновления необходимо отправить в базу данных), обрабатывается алгоритмом обнаружения изменений. Обнаружение изменений осуществляется путем обнаружения различий между текущими значениями свойств сущности и значениями исходных свойств, которые хранятся в моментальном снимке при запросе или присоединении сущности.

Автоматическое обнаружение изменений

Работа с состояниями сущностей

Answer 2

EF создаёт обёртку (proxy) над каждым объектом. Этот прокси содержит дополнительные свойства, одно из которых - состояние сущности (EntityState). Также там содержатся текущие и предыдущие значения сущности.

В псевдокоде эту выглядит так:

// entity
// Класс, который мы создали
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}
// proxy
// Класс, который генерируется
public class UserProxy
{
    public User Current { get; set; }
    public User Previous { get; set; }
    public EntityState State { get; set; }
    // другие свойства
    // ...
}

Когда мы добавляем, удаляем или изменяем сущности, то эти свойства соответственно меняются.

При вызове метода SaveChanges происходит примерно следующее:

foreach (UserProxy user in context.Users)
{
    if (user.State == EntityState.Added)
    {
        // выполняется sql-запрос INSERT
    }
    else if (user.State == EntityState.Deleted)
    {
        // выполняется sql-запрос DELETE
    }
    else if (user.State == EntityState.Modified)
    {
        // выполняется sql-запрос UPDATE
    }
}

Ещё раз повторю, что это псевдокод. На самом деле всё несколько сложнее.

READ ALSO
Нельзя выбрать базу данных

Нельзя выбрать базу данных

Вообщем на практике работаю в c# windows формах (в vs 2019)Хотел подключить базу данных

205
Бинарный поиск правой границы c#

Бинарный поиск правой границы c#

Нужно написать эффективную программу бинарного поиска поиска правой границы в упорядоченном массивеПрограмма должна удовлетворять условиям:...

189
Как превратить поле точек в GraphicsPath

Как превратить поле точек в GraphicsPath

Вопрос скорее не из программирования, а из алгоритмов

267
Предусмотреть в программе возможность завершения работы, если пользователь не активен в течении определенного времени. WPF,C#

Предусмотреть в программе возможность завершения работы, если пользователь не активен в течении определенного времени. WPF,C#

Как реализовать метод, который отслеживает активность окна WPF C#? Задача стоит следующая, необходимо предусмотреть возможность программы...

187