Как спроектировать домен с сущностью, ссылающейся на сущность, на другом сервере sql с постоянством NHibernate

Мне нужно спроектировать домен, который состоит из двух простых объектов:

public class User
{
    public virtual int Id { get; protected set; }
    public virtual string Email { get; protected set; }
    public virtual Country Country { get; protected set; }
    ...
}

public class Country
{
    public virtual int Id { get; protected set; }
    public virtual string Name { get; protected set; }
    ...
}

Все это хорошо и ясно в доменном мире, но проблема в том, что пользователь и страна сохраняются в двух разных базах данных на двух разных серверах (хотя они оба являются серверами MSSQL 2005).

Итак, как мне правильно реализовать постоянство сущностей на разных серверах sql в NHibernate?

Использование идентификаторов вместо объектов в ссылках? Да, это просто, но это сильно бьет по всему домену, делая объект домена более похожим на DTO. И для этого потребуется, чтобы IUserRepository получил доступ к ICountryRepository для загрузки сущности пользователя.

Связанные серверы? Хм... Что-то мне это не нравится (распределенные транзакции и отсутствие столбцов XML). И что я должен знать в случае их использования и, что более важно, как мне настроить NHibernate для эффективной работы с подключенными серверами?

Может какое другое решение?


person Michael Logutov    schedule 09.06.2012    source источник


Ответы (2)


Я слышал о людях, использующих свойство schema в сопоставлении классов для содержания имени связанного сервера (например, otherserver.dbo), но я не знаю никого, кто не сталкивался бы с той или иной проблемой при этом.

Существует несколько сред начальной загрузки DDD, которые позволяют вам прозрачно сопоставлять сущности с различными базами данных (в результате получается несколько ISessionFactories, которыми он будет управлять за вас). Я бы рекомендовал использовать NCommon. Это предполагает, однако, что Country существует только в одной базе данных, а User существует только в другой.

Что касается транзакций... ну, если вы используете TransactionScope и настроите DTS, это может сработать. NCommon использует UnitOfWork API, который также является оболочкой TransactionScope.

Вам придется изменить User так, чтобы Country был просто идентификатором. Вот почему. В итоге вы получите две фабрики сеансов, одна из которых имеет сопоставление для Country, а другая — для User. Если вы не сделаете это изменение, NHibernate будет жаловаться, что нет сопоставления для Country при сохранении User (поскольку они хранятся в двух разных БД).

Теперь вы можете указать NHibernate игнорировать свойство Country и оставить Country, чтобы ваш домен не изменился. Однако, когда вы в следующий раз загрузите User из базы данных, Country будет нулевым.

person moribvndvs    schedule 09.06.2012
comment
Хм... Просто поясню: NCommon позволит мне прозрачно сопоставлять объекты, и мне не придется менять модель домена или нет, она не может так работать, и мне придется изменить объект страны на объект значения countryId? - person Michael Logutov; 09.06.2012
comment
С NCommon вам все равно нужно будет изменить Country на CountryID и просто сохранить идентификатор. Я объясню, почему в обновленном ответе. - person moribvndvs; 09.06.2012
comment
Да я вижу. Но как это изменение поможет мне использовать NCommon? Если я правильно понял, мне все равно нужно будет вручную загрузить объект Country из другого репозитория - я мог бы сделать это без NCommon. - person Michael Logutov; 09.06.2012
comment
NHibernate поддерживает только одну строку подключения на ISessionFactory. У вас есть две базы данных, у вас есть две ISessionFactory. Вам не нужен NCommon, но он делает всю тяжелую работу по выяснению того, какой ISessionFactory использовать, чтобы получить ISession для сущности. - person moribvndvs; 09.06.2012
comment
Я изучил NCommon, и кажется, что разработка остановилась почти год назад - последняя фиксация была 11 месяцев назад, и в github есть несколько очень серьезных проблем (например, TransactionManager и UnitOfWorkManager не являются потокобезопасными). У вас есть опыт использования NCommon на рабочих веб-сайтах? - person Michael Logutov; 12.06.2012
comment
По общему признанию, прошло некоторое время с тех пор, как я использовал его, потому что я написал свой собственный фреймворк. Другим, который поддерживает отображения нескольких баз данных, и, вероятно, более активным, является SharpArchitecture. Однако, что касается потокобезопасности его единицы работы и менеджера транзакций: они предназначены для поддержки контейнера IoC для каждого запроса, поэтому я думаю, что жалобы людей коренятся в непонимании того, как он намеревался это работать. - person moribvndvs; 12.06.2012

Вы можете использовать NHibernate.Shards от NHContrib.

person Ivo    schedule 09.06.2012
comment
Разве это не первичное разделение? Можно ли его использовать для совершенно не связанной сущности, такой как Страна? И завершен ли код NHibernate.Shards, чтобы его можно было использовать в производстве? - person Michael Logutov; 09.06.2012
comment
Насколько мне известно, он поддерживает размещение сущностей в разных БД и может использоваться в производстве. - person Ivo; 09.06.2012
comment
Я вижу, что этот проект имеет тип альфа-версии :| - person Michael Logutov; 09.06.2012