Предложения о том, как сопоставить объекты домена (ORM) с объектами передачи данных (DTO)
Текущая система, над которой я работаю, использует Castle Activerecord для предоставления ORM (реляционное сопоставление объектов) между объектами Domain и базой данных. Это хорошо, хорошо и в большинстве случаев работает хорошо!
Проблема возникает с поддержкой Castle Activerecords для асинхронного выполнения, а точнее, SessionScope, который управляет сеансом, к которому принадлежат объекты. Короче говоря, плохие вещи случаются!
Поэтому мы ищем способ легко конвертировать (думать автоматически) из объектов домена (которые знают, что БД существует и заботится) для объекта DTO (которые ничего не знают о БД и не заботятся о сеансах, атрибутах сопоставления или все вещи ORM).
Есть ли у кого-нибудь предложения по этому поводу. Для начала я ищу базовое отображение объекта One to One. Объект домена Лицо будет отображаться как PersonDTO. Я не хочу делать это вручную, так как это отходы.
Очевидно, что на ум приходит отражение, но я надеюсь, что некоторые из лучших ИТ-знаний будут перемещаться вокруг этого сайта, что будет предложено "кулер".
О, я работаю в С#, объектах ORM, как сказано перед сопоставлением с Castle ActiveRecord.
Пример кода:
По запросу @ajmastrean у меня ссылка на пример, который я (плохо) издевался вместе. В примере есть форма захвата,
, , домен, активный реестр и async. Он немного большой (3 МБ), потому что я включил DLL ActiveRecored, необходимый для его запуска. Вам нужно будет создать базу данных под названием ActiveRecordAsync на вашем локальном компьютере или просто изменить файл .config.
Основные сведения о примере:
Форма захвата
Форма захвата имеет ссылку на contoller
private CompanyCaptureController MyController { get; set; }
При инициализации формы он вызывает MyController.Load() private void InitForm() { MyController = новый CompanyCaptureController (это); MyController.Load(); }
Это вернет обратно к методу LoadComplete()
public void LoadCompleted (Company loadCompany)
{
_context.Post(delegate
{
CurrentItem = loadCompany;
bindingSource.DataSource = CurrentItem;
bindingSource.ResetCurrentItem();
//TOTO: This line will thow the exception since the session scope used to fetch loadCompany is now gone.
grdEmployees.DataSource = loadCompany.Employees;
}, null);
}
}
здесь происходит "плохой материал", так как мы используем дочерний список компании, который настроен как "ленивая" загрузка.
Контроллер
У контроллера есть метод Load, который вызывается из формы, затем он вызывает помощник Asyc для асинхронного вызова метода LoadCompany, а затем возвращается к методу LoadComplete формы Capture.
public void Load ()
{
new AsyncListLoad<Company>().BeginLoad(LoadCompany, Form.LoadCompleted);
}
Метод LoadCompany() просто использует репозиторий для поиска известной компании.
public Company LoadCompany()
{
return ActiveRecordRepository<Company>.Find(Setup.company.Identifier);
}
Остальная часть примера является скорее обобщенной, она имеет два класса домена, которые наследуют от базового класса, установочный файл, чтобы заставлять некоторые данные и репозиторий предоставлять возможности ActiveRecordMediator.
Ответы
Ответ 1
Я решил проблему, очень похожую на это, когда я скопировал данные из множества старых контрактов веб-сервисов в контракты данных WCF. Я создал ряд методов, имеющих такие подписи:
public static T ChangeType<S, T>(this S source) where T : class, new()
В первый раз, когда этот метод (или любая другая перегрузка) выполняется для двух типов, он просматривает свойства каждого типа и решает, какие из них существуют как на основе имени, так и типа. Он принимает это "пересечение членов" и использует класс DynamicMethod для emil IL, чтобы скопировать тип источника в целевой тип, затем он кэширует полученный делегат в статический словарь в потоковом режиме.
Как только делегат создан, он неприлично быстро, и я предоставил другие перегрузки для передачи делегату для копирования свойств, которые не соответствуют критериям пересечения:
public static T ChangeType<S, T>(this S source, Action<S, T> additionalOperations) where T : class, new()
... чтобы вы могли сделать это для примера Person to PersonDTO:
Person p = new Person( /* set whatever */);
PersonDTO = p.ChangeType<Person, PersonDTO>();
И любые свойства как Person, так и PersonDTO (опять же, имеющие одинаковое имя и тип) будут скопированы с помощью метода времени исполнения, и любые последующие вызовы не должны быть испускаемыми, но будут повторно использовать один и тот же испускаемый код для тех, типы в этом порядке (т.е. копирование PersonDTO в Person также повлечет за собой удар, чтобы испустить код).
Это слишком много кода для публикации, но если вы заинтересованы, я приложу все усилия, чтобы загрузить образец в SkyDrive и отправить ссылку здесь.
Ричард
Ответ 2
используйте ValueInjecter, с ним вы можете отобразить что угодно, например,
- object ↔ object
- object ↔ Form/WebForm
- DataReader → объект
и он имеет классные функции, такие как: сплющивание и развязка
загрузка содержит множество образцов
Ответ 3
Вы должны автоматизировать, о котором я писал здесь:
http://januszstabik.blogspot.com/2010/04/automatically-map-your-heavyweight-orm.html#links
Пока свойства называются одинаковыми на обоих ваших объектах, Automapper будет обрабатывать его.
Ответ 4
Приносим извинения за то, что вы не ввели здесь подробные данные, но базовый подход OO должен был сделать DTO членом класса ActiveRecord и предоставить делегату ActiveRecord аксессуар и мутаторы для DTO. Вы можете использовать инструменты генерации кода или рефакторинга для быстрого создания классов DTO из классов AcitveRecord.
Ответ 5
На самом деле, теперь я полностью разобрался.
Потому что вы говорите: "Поэтому мы ищем способ легко конвертировать (думать автоматически) из объектов домена (которые знают, что БД существует и заботится) для объекта DTO (которые ничего не знают о БД и не заботятся о сеансах, атрибуты отображения или все ORM).
-
Объекты домена знают и заботятся о БД? Разве это не значит, что вся точка объектов домена содержит ТОЛЬКО бизнес-логику и полностью не знает о БД и ОРМ?... У вас есть эти объекты? Вам просто нужно исправить их, если они содержат все это... почему я немного смущен, как DTO входит в картину.
-
Не могли бы вы предоставить более подробную информацию о проблемах, с которыми вы столкнулись при ленивой загрузке?