Построение доменного объекта из нескольких DTO - PullRequest
4 голосов
/ 24 октября 2008

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

Предположим далее, что на каждом экране отображается только подмножество всех данных, содержащихся в объекте Customer.

Проблема в том, что когда пользовательский интерфейс передает данные обратно с каждого экрана (например, через DTO), он содержит только это подмножество полного объекта домена клиента. Поэтому, когда вы отправляете этот DTO на фабрику клиентов для повторного создания объекта Customer, у вас есть только часть клиента.

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

Итак, вопрос: как бы вы справились с этой проблемой?

Некоторые из моих идей:

  • включить аргумент в Репозиторий, указывающий, какая часть Клиент обновлять и игнорировать другие

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

ИМО, оба из них - кладжи. Есть еще идеи получше?

@ chadmyers: вот проблема.

Сущность имеет свойства A, B, C и D.

DTO # 1 содержит свойства для B и C.

DTO # 2 содержит свойства для C и D.

Пользовательский интерфейс запрашивает DTO # 1, вы загружаете сущность из хранилища, конвертируете ее в DTO # 1, заполняя только B и C, и передаете ее в UI.

Теперь пользовательский интерфейс обновляет B и отправляет DTO обратно. Вы воссоздаете сущность, и она заполнена только B и C, потому что это все, что содержится в DTO.

Теперь вы хотите сохранить объект, у которого заполнены только B и C, с A и D, пустыми / пустыми. Хранилище не может знать, следует ли ему постоянно обновлять A и D как пробелы или игнорировать их.

Ответы [ 4 ]

4 голосов
/ 24 октября 2008

Я бы использовал фабрику, чтобы загрузить полный объект клиента из хранилища после получения DTO. После этого вы можете обновить только те поля, которые были указаны в DTO.

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

3 голосов
/ 24 октября 2008

Это веб-приложение? Загрузите объект клиента из репозитория, обновите его из DTO, сохраните его обратно. Это не похоже на клочок для меня. :)

ОБНОВЛЕНИЕ: согласно вашим обновлениям (пример A, B, C, D)

Так что я думал о том, что когда вы загружаете сущность, она заполняется A, B, C и D. Если DTO # 1 только обновляет B & C, это нормально. A и D не затрагиваются (что является желаемой ситуацией).

То, что делает хранилище с обновлениями B & C, остается за ним. Например, если вы используете Hibernate / NHibernate, он просто выяснит это и выпустит обновление.

Тот факт, что DTO # 1 имеет только B & C, не означает, что вы также должны аннулировать A & D. Просто оставьте их в покое.

1 голос
/ 25 мая 2009

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

т.е.

dtoUser.MapFrom<In,Out>(Entity)
or
dtoAdmin.MapFrom<In,Out>(Entity)

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

entity.Foo = dtoUser.Foo
or
entity.Bar = dtoAdmin.Bar

entityRepsotiry.Save(entity) <-- do not pass DTO.

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

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

Вы упоминаете о хранении сущности где-то, зачем вы это делаете? Это работа вашего хранилища. Он решит, где взять Entity (db, cache, e.t.c), нет необходимости хранить его где-то еще.

Надеюсь, что это помогает распределить ответственность в вашем домене, это всегда проблема, и тут и там есть серая зона, но в целом это типичное использование Repository, DTO e.t.c.

1 голос
/ 10 февраля 2009

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

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

  2. Наличие нескольких DTO имеет смысл, если у вас есть страница результатов поиска, которая показывает большой объем записей и отображает только часть данных вашей сущности. В этом случае эффективно передавать на эту страницу только те данные, которые ей необходимы. Не имеет смысла передавать DTO, который содержит частичные данные, на страницу CRUD. Просто дайте ему полное DTO или даже полный объект сущности. Если он не использует все данные, ничего страшного.

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

  1. Вытащить полный DTO из хранилища или дБ
  2. Обновите DTO с любыми изменениями, внесенными через форму
  3. Сохранить полный DTO обратно в хранилище или дБ

Этот метод требует дополнительного попадания в дб, но это не является существенной проблемой в форме CRUD.

...