Entity Framework (Вопросы о POCO, контексте и DTO) - PullRequest
1 голос
/ 30 ноября 2011

За последние пару дней я читал об инфраструктуре сущностей и сумел понять, как ее использовать, но у меня все еще есть пара вопросов, некоторые из которых могут показаться слишком простыми.Для перспективы я использую Entity Framework 4.0 в веб-приложении asp.net. Если вы можете ответить на любой из вопросов, пожалуйста, продолжайте.

  1. Какое преимущество я получаю, используя шаблоны POCO.Я понимаю, что если я хочу получить постоянное невежество и не допустить, чтобы мои сущности были свободны от любой информации, связанной с хранилищами, POCO - это путь.Кроме того, я мог бы перейти с Entity Framework, чтобы сказать NHibernate с относительной легкостью при использовании объектов POCO?Помимо слабой связи, есть ли у меня существенная причина для перехода к организациям POCO.Также, если я использую POCO, я теряю что-нибудь.Я все еще получаю отслеживание изменений и ленивую загрузку с помощью прокси-серверов?

  2. Является ли обычной практикой использование сущностей модели EF в качестве объектов передачи данных или бизнес-объектов.то есть, например, у меня есть отдельная библиотека классов для моей модели сущности. Предположим, я использую MVP, где я хочу получить список сотрудников компании.Докладчик запрашивал мои функции бизнес-логики, которые запрашивали бы модель сущностей для списка сотрудников и возвращали список сущностей презентатору.В этом случае мой докладчик должен иметь ссылку на модель EF.Это правильный путь?В случае моего веб-приложения asp.net это не должно быть проблемой, но если я использую веб-сервисы, как это работает?Является ли это причиной перехода к сущностям POCO?

  3. Предположим, что сущность Employee имеет свойство навигации к таблице компании.Если я использую и заворачиваю контекст данных в блок «using» и пытаюсь получить доступ к свойству навигации в BL, я предполагаю, что получу исключение.Получу ли я также исключение, если отключу ленивую загрузку и воспользуюсь запросом 'include' linq, чтобы получить сущность?В предыдущем посте кто-то рекомендовал использовать контекст для каждого запроса, подразумевая, что контекст остается активным, даже когда я нахожусь в BL.Я предполагаю, что мне все еще нужно будет отсоединить объект и присоединить его к контексту при следующем запросе, если я хочу сохранить какие-либо изменения, которые я делаю?или вместо этого я должен просто запросить объект снова с новым контекстом и обновить его?

  4. Этот вопрос больше связан с организацией файлов / передовым опытом и является продолжением вопроса, который я опубликовал ранее.Когда я использую отдельные файлы на основе сущностей для организации своего уровня доступа к данным, лучше всего организовывать мои запросы, включающие объединения между несколькими таблицами.Я все еще немного туманен в организации.Попытка поиска в Интернете, но не было большой помощи.

1 Ответ

5 голосов
/ 30 ноября 2011

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

  1. Вы в значительной степени прибили преимущества использования POCO.Есть несколько явных преимуществ в отделении ваших бизнес-объектов (объектов POCO) от уровня доступа к данным.Но основная причина, как вы сказали, возможность изменить или изменить слои ниже.Однако, используя POCO, вы по сути следуете подходу Code First (CF).Лично я считаю это Code In Parallel в зависимости от вашего жизненного цикла разработки программного обеспечения.У вас все еще есть все навороты, которые есть у подхода к данным или модели, и некоторые из них, поскольку вы можете расширить DbContext, который является ObjectContext.Я прочитал статью, которую я не могу найти, что CF - это будущее Entity Framework.Наконец, с POCO приятно то, что вы можете включать правила проверки здесь или где-либо еще.Вы также можете предоставить прогнозы.Допустим, у вас есть Дата рождения, но вы также хотите иметь возраст.Теперь это становится легкой задачей, поскольку свойство Age игнорируется при сопоставлении с базой данных.
  2. Лично я создаю свои собственные бизнес-объекты (POCO) для больших проектов, которые, как правило, живут своей жизнью, где изменения являютсяобраз жизни.Другая мысль - это масштабируемость и ремонтопригодность.Что если в будущем я решу разделить функциональность между приложениями, в которых, как вы упомянули веб-сервисы, функциональность теперь предоставляется из двух разных мест.Если вы инкапсулировали свои бизнес-объекты и DAL в одном и том же разделении блоков кода или масштабируемость теперь стала немного более сложной.Однако рассмотрим проект.Он может быть небольшим с небольшими изменениями в будущем, поэтому не нужно бросать гранату, чтобы убить муху.В какое время данные могут быть первым способом, позволяющим файлу edmx представлять ваши объекты.Так что не женитесь на одной технологии или одной методологии / шаблоне.Делайте то, что имеет смысл для вашего времени и бизнеса.
  3. Использование заявлений совершенно нормально.На самом деле я недавно был включен, чтобы затем обернуть это в TransactionScope.Если возникает ошибка, откатам присуще.Далее нужно рассмотреть UnitOfWork.Шаблон UnitOfWork инкапсулирует моментальный снимок того, что должно быть выполнено, когда контекст данных является границами, с которыми вы работаете.Для каждого UnitOfWork у вас есть тема, по которой должна выполняться работа.Например, Сотрудник.Таким образом, если вы хотите сохранить информацию о сотруднике, чтобы сделать ее проще, вы должны позвонить в службу BL или хранилище (которое когда-либо).Там вы передаете идентификатор сотрудника, выполняете некоторую работу в этом модуле UnitOfWork, где он либо создается в конструкторе, либо использует инъекции зависимостей (DI или IoC).Простой старт - это StructureMap.Там служба совершает необходимые вызовы в ваш UnitOfWork (DbContext), а затем возвращает управление обратно в восходящий поток (например, UI).
  4. Лучший способ узнать здесь - это просмотреть код другого пользователя.Я бы начал с некоторых примеров Microsoft.Я бы начал с Nerd Dinner (http://nerddinner.codeplex.com/), затем построил бы это.

Дополнительное чтение:

Использовать шаблон прототипа или нет

http://weblogs.asp.net/manavi/archive/2011/05/17/associations-in-ef-4-1-code-first-part-6-many-valued-associations.aspx

[EDIT] NightHawk457, мне очень жаль, что я не ответил на ваши вопросы. Надеюсь, вы поняли это, но для будущих читателей ...

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

  • Уровень данных ( Доступ к данным ): MyDbContext: DbContext, IUnitOfWork, где IUnitWork заключает контракты на операции CRUD.
  • Репозиторий данных ( Доступ к данным / бизнес-логика ): MyDomainObjectRepository: IMyDomainObjectRepository, который получает IUnitOfWork классом Factory или внедрением зависимости. Вызывает проверку MyDomainObject для операций CRUD.
  • Модель домена ( Бизнес-логика ): MyDomainObject с использованием [Пользовательских] атрибутов проверки.Прочитайте это для плюсов / минусов.
  • MVVM / MVC / WCF ( Презентация / Сервисные уровни ): какие дополнительные слои вы выбрали,теперь у вас есть доступ к вашим данным, которые красиво упакованы в меньшие модули, которые самостоятельно инкапсулируют свои функции.Уровень представления (например, ViewModel, Controller, Code-Behind и т. Д.) Может затем получить IMyObjectRepository с помощью класса Factory или путем внедрения зависимостей.

Советы:

  • Передача строки подключения в MyDbContext, чтобы можно было повторно использовать MyDbContext.
  • MySql плохо работает с системой.Transactions.TransactionScope, пример .Я точно не помню, но MySql этого не поддерживал.Это делает тестирование немного сложным, так как мы создали этот уровень разделения.
  • Создайте тестовый проект для каждого слоя и при минимальной общей функциональности / правилах тестирования.
  • Каждый объект домена должен расширять базуобъект с идентификатором поля как минимум.Также не используйте ключевые атрибуты здесь.Доменный объект должен описывать не архитектуру, а конкретные данные как единое целое.Даже в Code First этого можно достичь с помощью Fluent API.
  • Подумайте об общих принципах при создании MyDbContext.;) Прочтите сообщение Диего .
  • В ASP.NET репозитории удобно использовать с ObjectDataSources.

Как видите, существует четкое разделениеролей, где IUnitOfWork и IMyDomainObjectRepository являются интерфейсами, которые предоставляют функциональность вышеперечисленных слоев.И, например, IUnitOfWork может быть NHibernate, Entity Framework, LinqToSql или ADO.NET, где все, что нужно изменить, - это изменение класса фабрики или регистрация внедрения зависимостей.К вашему сведению, я также слышал, что хранилище называется Service Layer.Лично мне нравится, чтобы имя не путали с веб-сервисами.Следующим большим отрывом от этой структуры является реализация области контекста базы данных (IUnitOfWork).Простым примером будет страница ASP.NET, где для каждой страницы есть один и только один IUnitOfWork для каждого репозитория или для этого объема работы.То же самое относится и к ViewModels, Controllers и т. Д. Итак, допустим, вам нужно использовать два репозитория, EmployeeRepository и HRRepository.Затем вы можете поделиться IUnitOfWork между обоими или нет.Чтобы пересечь границы страницы, ViewModel или Controller, мы используем ID для сущностей, где они затем извлекаются из БД, и работа выполняется.В качестве альтернативы вы можете передать DTO через границы и присоединиться к контексту, но затем вы начнете терять разделение слоев.

Чтобы продолжить, классы POCO не должны генерироваться автоматически.Фактически вы можете создавать свои классы сущностей с нуля и выполнять сопоставление в расширенном классе DbContext внутри метода OnModelCreating (DbModelBuilder mb).Начните здесь , затем здесь и обратите внимание на Дополнительные ресурсы, Google Fluent API и прочитайте эту запись Диего.

Что касается проверки, это интересный момент, потому что было бы здорово, если бы все бизнес-правила могли быть проверены в одном месте.Ну, как мы все знаем, это не очень хорошо работает.Итак, вот моя рекомендация: сохранить все проверки уровня данных (т. Е. Требуемые, диапазон, формат и т. Д.) С максимально возможной аннотацией данных в объекте домена и оставить проверку процесса в репозитории с четкими ролями репозитория (т. Е. Если (isEmployee) сделай это, иначе это).Я говорю ясно, что вы не хотите добавлять сотрудника в два разных репозитория, где проверка должна дублироваться.Чтобы вызвать проверку, запустите здесь .Захватите ValidationResults и отправьте в восходящий поток с MyRepositoryValidationException, который содержит коллекцию ошибок валидации (например, требуется Employee), которые могут быть представлены на уровне представления.После всего сказанного не забудьте выполнить проверку на уровне представления.Например, вы не хотите, чтобы посты возвращались, чтобы убедиться, что у сотрудника есть действующий адрес электронной почты.

Просто не забудьте сбалансировать время и усилия со сложностью.Для чего-то простого используйте Data First или Model First с файлом EDMX.Затем положите хранилище поверх того, что также содержит все правила проверки.

...