Должен ли я включить или отключить динамические прокси с помощью Entity Framework 4.1 и MVC3? - PullRequest
67 голосов
/ 18 августа 2011

Может ли кто-нибудь предложить какой-нибудь совет или указать несколько блогов / статей, которые могли бы помочь принять это решение? Прокси мне кажутся чуждыми, и я не решаюсь их использовать. Мне нравится возможность контролировать Lazy Loading с помощью виртуальных свойств в моей модели, но это почти все преимущества, которые я вижу. Мое приложение - это простое веб-приложение MVC, и мне не нужно подключать какие-либо хуки к контексту, когда сущности находятся в измененном состоянии.

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

Плюсы

  • При «Сохранить» или «Обновить» я получаю бесшовное с «Apply'Changes»
  • Конфигурация отложенной загрузки очень проста.

Против

  • Никогда ранее не использовал прокси для моих сущностей, это изменение в подход, который просто кажется неудобным для меня и товарищей по команде члены.
  • неудобно отлаживать.
  • Требуется дополнительный код, если я хочу сериализовать / десериализовать
  • В «Сохранить» или «Обновить» прокси должен быть тем же объектом, который был извлечен из контекста.

Ответы [ 5 ]

102 голосов
/ 18 августа 2011

Если вы говорите о динамических прокси в EF, то можно различить два разных типа:

  • Прокси для ленивой загрузки
  • Прокси для отслеживания изменений

Обычно прокси отслеживания изменений также может служить прокси для отложенной загрузки. Обратное неверно. Это связано с тем, что требования к прокси-серверам отслеживания изменений выше, особенно все свойства, а также скалярные свойства, должны быть virtual. Для отложенной загрузки достаточно, чтобы навигационные свойства были virtual.

Тот факт, что прокси-сервер отслеживания изменений всегда позволяет использовать ленивую загрузку, является основной причиной, по которой DbContext имеет этот флаг конфигурации:

DbContext.Configuration.LazyLoadingEnabled

Этот флаг по умолчанию имеет значение true. Установка false отключает отложенную загрузку, даже если созданы прокси. Это особенно важно, если вы работаете с прокси-серверами отслеживания изменений, но не хотите использовать их также для отложенной загрузки.

Опция ...

DbContext.Configuration.ProxyCreationEnabled

... полностью отключает создание прокси - для отслеживания изменений и отложенной загрузки.

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

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

На самом деле единственная причина, по которой я знаю, это производительность . Но это очень веская причина. Сравнивая отслеживание изменений на основе снимков с отслеживанием изменений на основе прокси-серверов, разница в производительности огромна - по моим измерениям коэффициент от 50 до 100 является реалистичным (взят из метода, который требовал около одного часа для 10000 циклов с отслеживанием изменений на основе снимков и от 30 до 60 секунд после того, как все свойства виртуальные, чтобы включить прокси отслеживания изменений). Это становится важным фактором, если у вас есть приложение, которое обрабатывает и изменяет многие (скажем, более 1000) сущностей. В веб-приложении, где вы, возможно, выполняете операции «Создать / Изменить / Удалить» только с отдельными объектами в веб-запросе, эта разница не имеет большого значения.

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

Но если вы хотите, чтобы разумная производительность обрабатывала много, у многих сущностей нет альтернативы изменению прокси-серверов отслеживания - кроме использования EntityObject производных сущностей в EF 4.0 (не вариант в EF 4.1, потому что это запрещено при использовании DbContext) или вообще не используете Entity Framework.

Редактировать (май 2012 г.)

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

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

15 голосов
/ 12 октября 2012

Для тех, кто использует Entity Framework 5, обязательно ознакомьтесь со статьей Performance Performance .Sections 5 NoTracking Queries и 8 Loading Related Entities предлагает информацию, необходимую для принятия обоснованного решения.Приветствия.

2 голосов
/ 24 сентября 2015

Я бы предложил НЕ использовать прокси. Динамическое создание прокси прерывает или создает сложности для компонентов, которые зависят от проверки типа во время выполнения.

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

0 голосов
/ 06 июля 2017

Использовать Automapper 4.2.1. Новая версия не имеет DynamicMap

var parents = parentsRepo.GetAll().ToList();
Mapper.CreateMap<Parent,ParentDto>();
var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);
0 голосов
/ 08 июня 2016

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

Например, хранящаяся закрытая переменная сущности в одном из моих классов (она реализовывалапакетный процесс), и я просматривал несколько миллионов записей, обрабатывал и вставлял их в пакеты, воссоздавая контекст данных для каждой n-записи, чтобы очистить память.Хотя я НИКОГДА не использовал закрытую переменную, EF связывал ее с моими новыми объектами (там была ссылка через свойство навигации), хотя я только устанавливал ссылочный идентификатор.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...