Должен ли я включать или отключать динамические прокси с инфраструктурой сущностей 4.1 и MVC3?

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

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

Pros

  • В "Сохранить" или "Обновить" я получаю бесшовную копию с помощью "Apply'Changes"
  • Конфигурация Lazy-Loading очень проста.

против

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

Ответ 1

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

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

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

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

DbContext.Configuration.LazyLoadingEnabled

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

Опция...

DbContext.Configuration.ProxyCreationEnabled

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

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

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

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

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

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

Изменить (май 2012)

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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