«Незавершенное» POCO на клиенте - могу ли я пополнить коллекции позже? - PullRequest
0 голосов
/ 23 марта 2011

У меня есть настройки с клиентом -> WCF -> POCO -> EF4.

Скажем, у меня есть список с буквой А. Объект A содержит среди других свойств огромный список объектов B, который не загружен по умолчанию. Когда определенное действие выполняется на клиенте, ему может потребоваться знать список объектов B ...

Если я загружаю сущности B для сущности A и присоединяю их к коллекции, сущность A фактически изменяется, и я предполагаю, что при сохранении сущности она также сохранит эти «новые» сущности B в сущности A?

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

Вопрос может сводиться к тому, как я могу заново заполнить POCO на стороне клиента, когда у меня есть только частичное POCO для начала, и я хочу избежать загрузки данных дважды и при этом все еще могу полагаться на EF4 для правильного сохранения объекта

Ответы [ 2 ]

0 голосов
/ 23 марта 2011

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

Ваше решение, вероятно, в настоящее время:

  • Клиент отправляет запрос в службу WCF
  • WCF использует EF для получения данных, закрытия контекста и возврата графа POCO или частичного графа обратно клиенту
  • Клиент изменяет граф POCO / частичный граф и отправляет измененные данные обратно в службу WCF
  • WCF создает новый контекст EF и сохраняет график POCO

Звучит просто, но это не так. На последнем шаге вы должны вручную объяснить новому контексту, что изменилось. Обычно это означает интенсивное взаимодействие с ObjectStateManager (в случае ObjectContext API) или DbChangeTracker (в случае DbContext API). Это также означает, что вы должны передать информацию об изменениях от клиента.

Например, предположим, что вы модифицируете сущность Order. Order сущность зависит от Customer сущности и имеет зависимые OrderItem сущности. Чтобы сделать это интересным, предположим, что элементы OrderItems должны обрабатываться различными складами, чтобы каждый склад имел доступ только к назначенным элементам.

  • На первом этапе вы запросите Order с одного склада
  • На втором шаге вы выйдете на пенсию Order без Customer и с поддержкой OrderItems.
  • На третьем шаге склад модифицирует севараль OrderItems как обработанный. Удаляет один OrderItem из-за снятого с производства продукта и добавляет еще один OrderItem для замены снятого с производства продукта. Из-за нехватки припасов некоторые предметы останутся без изменений. Склад отправляет Order обратно на сервер.
  • Что вы будете делать на четвертом шаге? Вы должны применить некоторые знания. Первым делом известно, что клиент не был отправлен клиенту, поэтому вы не можете изменить отношения с клиентом. В случае отношения внешнего ключа это означает, что CustomerId не может быть изменено. Теперь вы должны явно сказать, какой OrderItem был обновлен (= существует в БД), который не изменился (= не требуется никаких действий), который был вставлен (= должен быть вставлен), а худшая часть была удалена (если вы не посылайте некоторую информацию об удалении с клиента, которую вы не можете знать, не пересылая граф сущностей из базы данных).

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

Существует два основных подхода к решению этой проблемы:

  • Сначала загрузите граф сущностей и объедините изменения в граф. Затем сохраните прикрепленный (загруженный) график. Вы просто сравните загруженный граф сущностей с полученным графом сущностей и обработаете все необходимые обновления, удаления, вставки.
  • Используйте объекты самоконтроля вместо POCO, которые являются реализациями шаблона набора изменений и способны отслеживать изменения на клиенте. У STE есть некоторые недостатки , которые делают их бесполезными в определенных сценариях.

Существует также совершенно отдельный архитектурный подход, использующий DTO вместо прямых EOC POCO, но это приводит к тем же сложностям, что и у вас на данный момент.

0 голосов
/ 23 марта 2011

Добро пожаловать в n-уровневую разработку.

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

Я бы рекомендовал избегать распространения сущностей домена от уровня обслуживания (бизнеса) к клиенту.Если вы поймете, что сущности узнают о том, полностью ли они загружены, или на каком уровне они находятся в данный момент, они вряд ли являются "POCO", не так ли?

Итак, вы пишете метод службы "GetEntityWithAllDetails",Он должен взять объект GetEntityWithAllDetailsRequest и вернуть объект GetEntityWithAllDetailsResponse, содержащий все, что ожидает вызывающий сервис, и не более.

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

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

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

...