Преобразователь объектов против обертки объектов

Я был бы признателен за небольшую помощь здесь ...

Допустим, в приложении у нас есть уровень данных и уровень бизнес-логики. В DAL у нас есть следующий объект:

public class Customer {
    public string Name {get; set;}
    public ICollection<Address> Addresses {get; set;}
}

public class Address {
    public string Street {get; set;}
}

В BLL у нас есть следующие POCO:

public class CustomerDto {
    public string Name {get; set;}
    public ICollection<AddressDto> Addresses {get; set;}
}

public class AddressDto {
    public string Street {get; set;}
}

Сущности в DAL заполняются легким ORM и извлекаются из BLL с использованием репозитория. Бывший:

public class CustomerInformationService {

    private readonly ICustomerRepository _repository {get; set;}
    public CustomerInformationService (ICustomerRepository repository)
    {
         _repository = repository;
    }
    public class CustomerDto Get(int id)
    {
         var customerEntity = _repository.Get(id);

         var customerDto = /* SOME TRANSFORMATION HERE */

         return customerDTO;
    }
}

Мои вопросы касаются части /* НЕКОТОРЫЕ ПРЕОБРАЗОВАНИЯ ЗДЕСЬ */. В нашей команде идет дискуссия о том, как сделать «отображение».

Один из подходов заключается в использовании картографа, либо автоматического, либо ручного сопоставления. Второй подход заключается в использовании своего рода оболочки вокруг Entity и ссылке на DTO, чтобы сохранить операцию копирования между объектами. Что-то вроде этого:

public class CustomerDto
{
     private IEntity _customerEntity;

     public IEntity CustomerEntity { get {return _customerEntity;}}

     public CustomerDto(IEntity customerEntity)
     {
          _customerEntity = customerEntity;
     }

     public string Name 
     { 
          get { return _customerEntity.Name; }
     }
     public ICollection<Address> Addresses 
     { 
          get { return _customerEntity.Addresses; }
     }
}

Второй подход кажется мне немного странным, потому что _customerEntity.Addresses выглядит как утечка (ссылка _customerEntity) между моим DAL и моим BLL, но я не уверен.

Есть ли преимущества/недостатки использования одного подхода по сравнению с другим?

Дополнительная информация: Обычно мы тянем макс. 1000 записей за раз, которые необходимо преобразовать между Entity и DTO.


person Gabriel Lopez    schedule 14.02.2017    source источник
comment
Если вы собираетесь использовать подход-оболочку, вы можете просто использовать сущности и забыть об использовании объектов dto. Вы ничего не покупаете с оберткой, но добавляете тесную связь и другую зависимость.   -  person dbugger    schedule 14.02.2017
comment
@dbugger - спасибо за ответ. Какую зависимость вы имеете в виду? BLL всегда будет знать интерфейсы из DAL, независимо от того, используем ли мы сопоставитель или оболочку для создания DTO.   -  person Gabriel Lopez    schedule 14.02.2017


Ответы (2)


Вы не упомянули свой легкий ORM. Я отвечу в двух разделах.

Если вы используете ORM, который создает прокси

Вам следует избегать выставления сущностей за пределы определенных границ. ORM, такие как NHibernate/EF, реализуют ленивую загрузку на основе прокси. Если вы выставите Entities на уровень приложения/UI, у вас будет мало контроля над поведением ORM. Это может привести ко многим неожиданным проблемам, и отладка также будет очень сложной.

Обертывание сущностей в DTO ничего не даст. Вы все равно получаете доступ к сущностям.

Использование DTO и их сопоставление с помощью какого-либо инструмента сопоставления, такого как AutoMapper, является здесь хорошим решением.

Если вы используете ORM, который не создает прокси

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

В случае, если вы решите использовать DTO, обертывание сущностей в DTO не имеет смысла. Если вы все равно хотите использовать Entity, зачем его обертывать? Опять же, может помочь такой инструмент, как AutoMapper.

См. этот вопрос. Это немного другое; Я спрашиваю Да/Нет, а вы спрашиваете Как. Но все же это поможет вам.

person Amit Joshi    schedule 15.02.2017
comment
Спасибо А_Ж. Потребовалось некоторое время, чтобы урегулировать дискуссию, но различие, которое вы провели между ORM с прокси и без прокси, нам очень помогло. В нашем случае ORM не генерировала прокси, но сущности нуждались в специальных атрибутах, чтобы ORM мог их сопоставить. Поскольку мы не хотели раскрывать эти атрибуты в других слоях, в итоге мы обернули их в DTO и использовали автосопоставление. - person Gabriel Lopez; 28.02.2017

Ставлю на подход сервисного уровня. В основном потому, что то, что выглядит как бизнес-объект или объект домена, не имеет ничего общего с DTO.

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

person Matías Fidemraizer    schedule 14.02.2017
comment
На самом деле, для меня ручное сопоставление в большой кодовой базе может быть лишь симптомом синдром гордого разработчика! - person Matías Fidemraizer; 14.02.2017