Specification для EF

Сложность 200-300

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

Некоторое время назад я писал о фасаде доступа к данным на основе Linq2Sql и в этом подходе важную роль играл паттерн «спецификация», с помощью которого модифицировались запросы к базе данных для получения минимальной выборки, чтобы процесс фильтрации проходил средствами SQL сервера, что правильно. Хотелось бы данный подход распространить и на EF, однако все оказалось на первый взгляд не так просто и радужно как в L2S. Однако с помощью интернета и смекалки все трудности были успешно разрешены, и сейчас я расскажу, как это было решено.

Подготовка

Перед тем как собственно приступить к рассказу о реализации, необходимо немного времени уделить подготовке кода и исходных данных, с которыми будем работать. Использовать я собираюсь EF5 RC Code First и соответственно .Net 4.5. В качестве модели данных пусть у нас будет класс героев, для разнообразия (правда со свойствами класса фантазия наверно подкачала).

Заполнение базы будем делать с помощью специального класса HeroicInitializer, приведу пару строчек заполнения:

Подробнее

EF5 Секреты метода DetectChanges — II

Отключение автоматического определения изменений

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

Даже если приложение забирает многие тысячи объектов и держит контекст, то вам возможно все равно не следует отключать автоматические обновления, если обращения к методам дергающим DetectChanges() происходят не часто. Типичным примером обратного поведения, т.е. частого обращения к методам нуждающихся в определении изменений может служить следующий пример:

В данном примере каждый вызов метода Add() (так же будет и с Attach()) дергает метод DetectChanges() и если постов очень много, то такая запись может стать очень дорогой. Для избегания накладных расходов в этом случае, стоит отключить автоматическое обнаружение изменений.

Использование try\finally гарантирует, что автоматическое обнаружение изменений всегда включится обратно.

Подробнее

EF5 Секреты метода DetectChanges — I

Секреты в том смысле, что это вещи, которые захочется знать EF гику.

Отслеживание изменений при работе с Entity Framework обычно не требует от разработчика каких-то особенных действий или размышлений. Тем не менее, отслеживание изменений и работа метода DetectChanges() является ключевым моментом и основной дилеммой между легкостью использования и производительностью. По этой причине было бы неплохо знать как именно работает метод DetectChanges(), что при этом происходит, для того чтобы принимать осознанные решения в случае модификации поведения при получении изменений, если ваше приложение ведет себя не так как задумывалось.

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

 

Проблема определения изменений

Большинство современных приложений, я думаю, используют простые POCO объекты, которые не знают о методе своего сохранения в базу данных. При работе с POCO объектами используется алгоритм сравнения данных, основанный на первоначальном «снимке» объекта (Snapshot). Это значит, что в самом объекте POCO нет никакой логики, которая позволяла бы отслеживать изменения и уведомлять об этом контекст БД.

Подробнее

EF5 Особенности использования прокси отслеживания изменений

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

  • Не стоит использовать наследование от EntityObject или IPOCO вообще. Нет никаких плюсов в их использовании.
  • Используйте POCO сущности и сделайте навигационные свойства виртуальными, чтобы можно было получить плюсы ленивой загрузки.
  • Если вы сериализуете свои сущности, тогда стоит подумать о том, чтобы выключить прокси и отказаться от ленивой загрузки, так как восстановление объектов может быть проблематичным.

Да, пока ни слова об использовании прокси отслеживания изменений. Для того, чтобы указать на случаи из использования следует рассмотреть их более детально с технической точки зрения, на плюсы и минусы которые возникают по сравнению с POCO объектами.

Подробнее

EF5 типы поддерживаемых сущностей

В результате копания во внутренностях EntityFramework я наткнулся на change-tracking proxies, которые с одной стороны натолкнули меня на мысль создания self-tracking objects для обычных объектов с помощью PostSharp. Однако перед началом рассказа о прокси-объектах изменения состояния, стоит рассказать о других классах объектов поддерживаемых  EF. Далее идет их описание в хронологическом порядке, как они был реализованы/введены во фреймворк.

Сущности, наследуемые от EntityObject

Единственный тип сущностей, поддерживаемый в самой первой предварительно реализации EF, были классы наследуемые от класса EntityObject, входящего в пространство имен EF. Наследование от EntityObject предоставляло ряд сервисов, таких как:

  • отслеживание изменений состояния свойств класса,
  • управление связями между сущностями,
  • работа с первичными и вторичными ключами.

Существование такого базового класса позволяло весьма эффективно EF управлять сущностями.

Минусом такого подхода, и очень БОЛЬШИМ минусом , было то, что бизнес-объекты и слой доступа данных (EF) были связаны более чем тесно, к тому же это нарушает принцип persistence-ignorance, т.е. объект не должен знать и завязываться на то как именно он сохраняется. Это была одна из причин, по которой я долгое время игнорировал и не стремился использовать в работе Entity Framework. К тому же, на практике, наследование от EntityObject делало работу с бизнес-объектами сложнее и полной специфичного для EF кода.

Сущности, наследуемые от EntityObject поддерживаются EF1 и EF4, но не DbContext и CodeFirst, которые были введены в версиях EF4.x.

Подробнее

EF5 шаблонный AddOrUpdate

Сложность 400

Продолжаю разбирать и ковырять Entity Framework на предмет его использования в реальной жизни, какие плюсы есть, чего стоит опасаться, какие сценарии использования наиболее продуктивны, и как его можно использовать в существующих сценариях.

Одним из таких сценариев, который дает о себе знать сразу, как только вы начинаете использовать EntityFramework в более-менее настоящем проекте, а не в синтетических тестах и приложениях – это вопрос добавления и обновления данных.

Не каждый раз и не во всякой ситуации можно отталкиваться и работать с объектами связанными с контекстом базы. Особенно если это какое-либо веб-приложение, хотя и в корпоративном десктопном ПО хватает примеров. Чаще всего требуется по каким-либо косвенным признакам определять новый объект или нет, или же производить поиск в базе по первичным ключам, и далее уже решать, сохранять или добавлять элемент.

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

Подробнее

EF5 Описание команд миграции

Основное управление скриптами миграциями для Entity Framework осуществляется из консоли менеджера пакетов, которая суть есть PowerShell, и во многих уроках и разборах упоминаются лишь базовые команды и опции, и не особенно фигурируют другие возможности. Решено было озаботиться составлением такого списка.

Основных команд, как и ожидалось всего 4:

  • Enable-Migrations – включает возможность миграции в EF
  • Add-Migration – добавляет/генерирует новую миграцию
  • Update-Database – обновление базы данных
  • Get-Migrations – показывает какие обновления были применены к БД

EF5 RF CF — Force Recovery Mode

Сложность 200

Или как заставить базу думать, что у вас новая модель.

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

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

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

Подробнее

EF5 RC CF — Механизм миграции

Entity Framework 5 Release Candidate Code First: Механизм миграции

Сложность 200.

Видимо настал тот момент, когда можно обратиться к Entity Framework, тем более что поступающая информация все сильнее и сильнее радует меня и EF обретает любопытные черты и свойства. Пятая версия фреймворка, в моих глазах уже может претендовать на то, чтобы появиться в боевой среде.

Более всего меня увлекает на данный момент подход CodeFirst, с возможностью миграций, т.е. поддержкой версионности базы. Очевидно на многих, достаточно простых сценариях, миграции отрабатывают хорошо, генерируя скрипты миграции вверх и вниз. Что весьма и весьма полезно. Однако нашлась ложка дегтя в этой бочке меда, либо я чего-то специфического не знаю, о чем все молчат =). Но обо всем по порядку.

Подготовка

Нам понадобится база данных MS SQL. В моем случае это SQL Server 2012, вы можете поставить себе Express версию, хотя скорее всего она уже есть у вас. Далее понадобится .net framework не ниже 4 версии. Конечно же Visual Studio и менеджер пакетов NuGet.

Начнем с создания простого консольного приложения, так как нам будет важен сам факт сохранения и чтения данных.

Подробнее