Управление DTO и отображением в большом проекте .NET - PullRequest
8 голосов
/ 06 июля 2011

Моя команда и я создаем большие приложения .NET WinForms. Приложение использует различные «Сервисы» для получения данных из нашей базы данных. Каждый «сервис» живет в своем собственном решении и обрабатывает данные определенного типа. Так, например, наш «ContactsService» управляет поиском / сохранением контактов в нашей базе данных.

Как правило, мы строим DTO для каждой службы. Таким образом, у нас может быть «ContactDTO», который имеет простые строковые свойства для каждого фрагмента данных в контакте. Теперь у нас также есть класс «Контакты» бизнес-уровня, который имеет точно такие же свойства, и, возможно, несколько дополнительных методов с некоторой бизнес-логикой. Кроме того, у "ContactsService" есть свой собственный класс Contact, который гидратируется из ContactDTO.

Управлять всеми нашими DTO и составлением карт стало огромной болью. В настоящее время отправка контакта для сохранения в базе данных выглядит так:

  • Карта клиента Contact to ContactDTO
  • Карта КонтактDTO к сервису Контакт
  • Сохранить контакт
  • Сервис карт Контакт для контактаDTO
  • Карта КонтактDTO к клиенту Контакт

Это просто кажется дерьмом. Если мы добавим свойство в наш класс Contact клиента, мы должны добавить свойство и сопоставления в 3-4 местах.

Что мы делаем неправильно и как мы можем облегчить нашу жизнь? Будет ли проще использовать что-то вроде Json.NET и иметь JSON DTO? Мы проверили AutoMapper, но некоторые члены команды подумали, что это слишком сложно.

Ответы [ 3 ]

2 голосов
/ 07 июля 2011

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

При использовании WCF макет, который я предпочитаю, выглядит примерно так (на примере вашего контакта):

  • Клиентская сборка
    • Контакт (имеет клиентские характеристики)
  • Сборка общих контрактов
    • Контакт (согласованный общий DTO)
  • Сборка прокси
    • Использует контакт из общей сборки контрактов
  • Сервисная сборка
    • Контакт (имеет характеристики бизнес-логики обслуживания, например, это может быть тип, предоставляемый уровнем ORM, таким как Entity Framework)

Сейчас я делюсь контрактами между службой и клиентом. Если мне когда-нибудь потребуется независимая версия, тогда я могу просто сделать копию общей сборки Contracts и переназначить сборку Proxy, чтобы использовать копию, а затем изменить обе сборки Contracts независимо. Но в большинстве случаев, в которых я работал, у меня есть и клиент, и сервис, поэтому удобно распределять сборку Contracts между ними.

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

Редактировать: Если вы не используете WCF, вам, очевидно, не понадобится сборка «Прокси».

0 голосов
/ 07 июля 2011

Рассмотрим некоторые вещи, которые необходимо ускорить в процессе:

Я написал генераторы кода, чтобы вы могли выбирать таблицы и столбцы из базы данных и генерировать C # DTO.Это экономит много ненужной печати и может генерировать DTO намного быстрее.Немного времени вперед, но когда у вас есть таблица с 20 столбцами, вам нужно отобразить ее, это помогает.

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

Используйте каркас сущностей или ORM mapper для бэкенда.Это может сэкономить много времени, но вы должны инвестировать в знания ORM и узнать, как это работает.

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

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

0 голосов
/ 07 июля 2011

AutoMapper не особенно сложен. Если вы следуете конвенциям, например, Contact.Address1 становится ContactAddress1 в DTO, вам не придется писать много кода, кроме вызова Mapper.Map. В качестве альтернативы вы можете использовать генерацию кода, но все равно будет сложно управлять изменениями.

Могу ли я спросить, почему вы чувствуете необходимость иметь и ContactDTO, и сервисный контакт? Можете ли вы не просто передать сервис Контакт вокруг? Я знал, что это не лучшая практика, но это может спасти вас от RSI

РЕДАКТИРОВАТЬ: Не обращайте внимания на мой последний пункт - по какой-то причине я подумал, что вы сопоставляете службу Контакт с сущностью базы данных, такой как NHibernate / Entity Framework

...