Должен ли я включать или отключать динамические прокси с entity framework 4.1 и MVC3?


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

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

плюсы

  • на "Сохранить" или "обновить", я получаю бесшовные с "применить" изменения
  • ленивая загрузка конфигурации очень легко.

минусы

  • никогда раньше не использовал прокси для моих сущностей, это изменение подойдите к этому просто кажется неудобным для себя и товарищей по команде члены.
  • неудобно отлаживать.
  • требуется дополнительный код, если я хочу сериализовать / де-сериализовать
  • при 'Save' или 'Update' прокси должен быть тем же объектом, который был получен из контекста.
5 66

5 ответов:

если вы говорите о динамических прокси в 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.

Edit (Май 2012)

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

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

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

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

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

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

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

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

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

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

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

var parents = parentsRepo.GetAll().ToList();
Mapper.CreateMap<Parent,ParentDto>();
var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents);