«правильный» способ загрузки частичные/отфильтрованные/критериев на основе списков под NHibernate является использование запросов. Существует lazy="extra"
, но он не делает то, что вы хотите.
Как вы уже отметили, это нарушает модель DDD Root Aggregate -> Children. Я боролся с этой проблемой только в абсолютном возрасте, потому что, прежде всего, я ненавидел то, что соответствовало постоянству, касающемуся загрязнения моей модели домена, и я никогда не смог бы получить поверхность API, чтобы выглядеть «правильно». Методы фильтрации в классе владеющих сущностей работают, но далеки от хороших.
В конце концов, я решил расширить свой базовый класс сущности (все мои сущности унаследованы от него, что, как я знаю, в настоящее время немного немодно, но, по крайней мере, позволяет мне делать подобные вещи последовательно) с защищенным методом, называемым Query<T>()
, который принимает выражение LINQ, определяющее взаимосвязь, и под капотом в репозитории вызывает LINQ-to-NH и возвращает IQueryable<T>
, который затем можно запросить по мере необходимости. Затем я смогу украсить этот вызов под обычным свойством.
Базовый класс делает это:
protected virtual IQueryable<TCollection> Query<TCollection>(Expression<Func<TCollection, bool>> selector)
where TCollection : class, IPersistent
{
return Repository.For<TCollection>().Where(selector);
}
(Здесь я должен отметить, что моя Repository реализация реализует IQueryable<T>
непосредственно, а затем делегирует работу вплоть до NH Session.Query<T>()
)
И facading как это работает :
public virtual IQueryable<Form> Forms
{
get
{
return Query<Form>(x => x.Account == this);
}
}
Это определяет связь списка между учетной записью и формой как обратную к фактической карте (Форма -> Аккаунт).
Для «бесконечных» коллекций - там, где есть потенциально неограниченное количество объектов в наборе - это работает нормально, но это означает, что вы не можете сопоставить отношения непосредственно в NHibernate и, следовательно, не можете использовать свойство непосредственно в NH, только косвенно.
Нам нужна замена общего пакета NHibernate, список и набор реализаций, которые знают, как использовать LINQ-провайдер для непосредственного запроса в списки. Один из них был предложен как патч (см. https://nhibernate.jira.com/browse/NH-2319). Поскольку вы можете видеть, что патч не был закончен или принят, и из того, что я вижу, предложение не переупаковывало это как расширение - Диего Мигельсон - пользователь здесь, на SO, поэтому, возможно, он перезвонит ... У меня есть проверил свой предложенный код как POC, и он работает как рекламируемый, но, очевидно, он не проверен или не гарантирован или не завершен, он может иметь побочные эффекты и без разрешения использовать или публиковать его, вы все равно не сможете его использовать.
До тех пор, пока команда NH не столкнется с написанием/принятием патча, в результате чего это произойдет, нам придется продолжать использовать обходные пути. Здесь NH и DDD имеют противоречивые взгляды на мир.
Итак, ваши объекты имеют зависимость от репозитория (или нескольких хранилищ, если на то пошло)? Это распространено в DDD? – bitbonk
Наверное, нет. Я бы описал наш подход как вдохновленный DDD, но не рабски следя за ним. В нашем сценарии нет никакого огромного недостатка в этом - если бы я был «чистым», тогда я сделал бы это по-другому. Но у кого есть время для чистого? :-) –
Ну, я думаю, по крайней мере, мне нужно, чтобы мой IRepository был введен в мою Entity (желательно ctor-injected). Вы делаете это с окружающим контекстом, который временами бывает немного проблематичным. В чем причина вашего решения? – bitbonk