пятница, 20 апреля 2012 г.

NoTracking в Entity Framework

Начну с небольшой зарисовки для понимания.
Entity Framework это программная прослойка, которая преобразует ваши запросы в SQL и передает их в реальную базу. Полученные ответы обрабатываются и записываются в виде объектной модели в памяти. Поясню на примере. Т.е. каждый раз, как вы получили что то из БД, оно осело в большом обхекте типа DataContext. Каждый раз, когда вы вызываете SaveChanges все эти загруженные в память объекты просматриваются на предмет не поменялись ли они и, соответственно, не пора ли их записать в базу данных. Т.е. загружая из базы записи в ComboBox стартового окна, вы будите хранить их в памяти до тех пор, пока приложение не закроется. Даже если они вам больше не нужны.
Пусть у нас есть модель из вот такой таблички:
Написав вот такой код:
static void Main(string[] args)
{
   ExampleEntities context = new ExampleEntities();
   var types = context.Types;
   foreach (var item in types)
   {
     Console.WriteLine("Name = {0}", item.Name);
   }
   Console.ReadKey();
}

При наличии трех записей в БД, мы вполне логично увидим на экран 3 строки (у меня там названия: "Первый", "Второй", "Третий").
Чуть модифицируем код.
Для начала добавим вот такой метод:
private static void PrintLocalEntitiesCount(ExampleEntities context)
{
   Console.WriteLine(
     context.ObjectStateManager.GetObjectStateEntries(
       EntityState.Added 
       | EntityState.Modified
       | EntityState.Unchanged
     ).Where(e => e.Entity is Type)
     .Count());
}


Он нам позволит смотреть сколько объектов сейчас в "локальной" памяти Entity Model. Теперь вставим три его вызова в основной код:
ExampleEntities context = new ExampleEntities();
PrintLocalEntitiesCount(context);
var types = context.Types;
PrintLocalEntitiesCount(context);
foreach (var item in types)
{
   Console.WriteLine("Name = {0}", item.Name);
}
PrintLocalEntitiesCount(context);
Console.ReadKey();

Как вы думаете, что будет выведено на экран каждым из методов печати количества сущностей в локальной объектной модели? Посчитали? Проверьте себя увеличив картинку:
Совпало? Ну даже если программа обманула ваши ожидания, все равно видно, что после выполнения вывода на экран информации о трех типах, они остались в памяти.
Так вот, это все была присказка. Теперь сказка, как сделать так, чтобы и данные вывести на экран, и в памяти их потом не держать?
На самом деле, легко! Все что нужно, это чуть модифицировать запрос.
Вместо:
var types = context.Types;
Написать:
var types = context.Types.AsNoTracking();
Запускаем:
Все. Данные на экране видим, а в локальном кэше их нет. Что и требовалось.

Комментариев нет:

Отправить комментарий