Путаница между DTO (linq2sql) и объектами классов!
-
19-09-2019 - |
Вопрос
я успешно работаю с linq2sql и linq DTO (классами, созданными linq2sql)....
Я в замешательстве, у меня есть задача обновить старое приложение, и я вижу, что мои DTO будут использоваться так, как и должны....дата транспортировки
Я использую шаблон репозитория, поэтому передаю данные из репозитория в службу через dtos linq2sql...как только я нахожусь на уровне обслуживания (это, по сути, моя бизнес-логика), мне нужно передавать объекты классов..
эти объекты классов по сути являются зеркальным отражением (более или менее) dtos - в некоторых местах есть некоторые изменения, но в целом они такие же.
Итак, возвращаясь к поставленному вопросу!- это хорошая практика использовать dtos только для транспортировки данных из репозитория на уровень обслуживания...и однажды на уровне обслуживания (бизнес-логика) мне нужно лишь СОСТАВИТЬ все мои dtos с частями объекта класса (конечно, с использованием automapper!!)
Моя другая альтернатива - продолжать использовать DTOS, например объекты класса, и передавать их от метода к методу, в качестве возвращаемых типов и т. д., но я чувствую, что это плохая практика, и продолжаю ходить по кругу, задаваясь вопросом, какой метод мне следует применить?
Любая помощь действительно ценится
Спасибо
Решение
Вот мое мнение:При работе с любым нетривиальным приложением.Использование объектов linq2Sql в качестве модели предметной области — очень плохая идея.Я рассматриваю linq2Sql как ORM и не более того.Базы данных (которым linq2Sql имеет прямое соответствие) — это нормализация данные.Классы (в смысле OOAD) представляют собой нормализацию поведение (не данные).
[эти объекты класса по сути являются зеркальным отражением]...
Я столкнулся с этим при создании приложений с помощью linq2Sql.Давайте будем реалистами... большинство бизнес-приложений — это прославленные CRUD-приложения.Поэтому не исключено, что большой процент сущностей вашего приложения будет напрямую соответствовать таблицам базы данных. Я не хотел быть привязанным напрямую к сгенерированным DTO, но в то же время я не хотел, чтобы дублированные классы были разбросаны по всему моему приложению.
Итак, вот мое решение:
Я «запрограммировал интерфейс».
Допустим, у меня есть PersonDto
(Dto означает «Объект передачи данных») со свойствами FirstName, LastName, Age
(которые относятся непосредственно к столбцам базы данных).
Я создал IPerson
интерфейс и попросил моего PersonD реализовать его.
[Table(Name="Persons")]
internal class PersonDto : IPerson
{
....
}
И мой метод репозитория будет принимать и извлекать IPerson
в отличие от класса Linq2Sql.
IPerson somePerson = _repository.Get(someGuid);
somePerson.FirstName = "SomeName";
_repository.Save(somePerson);
Этот подход сработал для меня очень хорошо.Всякий раз, когда я чувствую, что мне нужно отойти от DTO, я могу сделать это довольно легко, поскольку интерфейс представляет мой объект, а не DTO.
Некоторые общие указания:Создавайте свои DTO вручную... Я знаю, это звучит безумно, но вы обнаружите, что это очень хорошо работает при нисходящем подходе к разработке через тестирование.Объекты вашего DTO (linq2Sql) будут очень легкими и будут открыты для изменений за пределами дизайнера .dbml.
Держите ваши DTO и DataContext внутренними.Нет никаких оснований для публичного доступа к вашим dto (учитывая, что у вас есть общедоступные интерфейсы для ваших репозиториев и объектов домена).Это приведет к логическому разделению модели вашей предметной области и доступа к данным.
Поместите весь уровень доступа к данным в отдельный проект (опять же, чтобы обеспечить такое разделение).
Поместите объявления интерфейса в отдельный проект (это гарантирует, что вы не столкнетесь с циклическими ссылками).
Надеюсь это поможет...
Другие советы
На самом деле у меня был похожий вопрос по этой теме, хотя мои намерения были немного другими.Было рекомендовано использовать классы Linq2SQL в качестве объектов домена и использовать преимущества частичных классов, как уже упоминали другие.Меня больше всего беспокоила форма этих объектов (т. е. имена свойств) и доступность членов класса (т. е. частные или частные объекты).защищен, например).
Форму объектов и даже доступность можно решить с помощью шаблонов t4, где Дэмиен Гард собрал шаблон T4, позволяющий вам контролировать форму классов, которые Linq2Sql будет генерировать для вас.Это можно увидеть здесь Шаблон T4 для Linq2SQL.
Это подход, который я собираюсь изучить и посмотреть, решит ли он мои проблемы.Кроме того, если ваш уровень обслуживания может принимать интерфейсы для аргументов метода, вы также можете контролировать, к чему имеет доступ уровень обслуживания, через оболочки интерфейса вокруг ваших DTO Linq2SQL.
Надеюсь это поможет.
Это одно из лучших обсуждений этой темы, которое я видел:
http://blog.wekeroad.com/blog/linqtosql-momma-said-knock-you-out/
В конце концов, решения о связывании и сплоченности носят ситуативный характер, и вам придется решить, что лучше всего подходит для вашей ситуации.
Когда ваше приложение перерастет LinqToSql, насколько легко будет вытащить LinqToSql и вставить на его место другой ORM?Это то, над чем вам следует серьезно задуматься.
В общем, сведите к минимуму знания вашего бизнес-уровня о LinqToSql.LinqToSql должен быть полностью скрыт от вашего уровня пользовательского интерфейса (ваш бизнес-уровень составляет значительную часть этого щита).С LinqToSql очень легко пойти по неправильному архитектурному пути, и может быть очень трудно вернуться на правильный путь постфактум.
Классы, созданные конструктором linq2sql, являются частичными классами, поэтому вы можете расширить их и поместить в них свою бизнес-логику.Идея состоит в том, что linq используется для сохранения/реконструкции этих объектов, чтобы вы могли избежать того отображения, о котором вы говорите.