Это правильное использование DTO? - PullRequest
5 голосов
/ 10 июня 2011

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

public interface IBalanceSheetRepository
{
    IEnumerable<BalanceSheetRecordDTO> GetBalanceSheetRecords();
}

public class BalanceSheetRepository : IBalanceSheetRepository
{
    DBContext _context;

    ...

    public IEnumerable<BalanceSheetRecordDTO> GetBalanceSheetRecords()
    {
        ObjectResult<BalanceSheetRecord> results = _context.GetBalanceSheet();
        return results.Select(CreateBalanceSheetDTOFromDAO);
    }

    private static BalanceSheetRecordDTO CreateBalanceSheetDTOFromDAO(BalanceSheetRecord dao)
    {
        return new BalanceSheetRecordDTO { ... };
    }
}

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

Вот мой вопрос: поскольку тип DTO используется в сигнатуре метода интерфейса репозитория, и поскольку мой BLL в конечном итоге будет использовать репозиторий и ему будет возвращена коллекция DTO, это, похоже, является сквозной проблемой. Поэтому у меня DTO живет в отдельной сборке «Инфраструктура» вместе с интерфейсами репо. Это хорошая практика для того, чего я пытаюсь достичь, или я где-то ошибся?

Кроме того: это плохая практика для обновления контекста данных в моем хранилище? Является ли некоторое количество сцепления нормальным, когда оба компонента принадлежат DAL? Я хочу использовать DI, но он кажется более полезным для замены реализации репозитория DBContext, например, на TestBalanceSheetRepository.

1 Ответ

6 голосов
/ 10 июня 2011

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

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

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

Ваш контекст данных - это ваша единица работы.Идея «одна единица работы на репозиторий» является анти-паттерном.Единицы работы должны быть ограничены уровнем обслуживания, который может включать 1-много объектов из 1-многих хранилищ.Если у каждого репозитория есть разные единицы работы, вы теряете возможность легко поддерживать согласованные транзакции на вызовах уровня обслуживания.

...