«Правильный» способ загрузки частичных/отфильтрованных списков/списков на основе критериев в 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);
}
(Здесь я должен отметить, что моя реализация репозитория реализует IQueryable<T>
напрямую, а затем делегирует работу NH Session.Query<T>()
)
И фасад работает так:
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 просто противоречивые взгляды на мир.
person
Neil Hewitt
schedule
20.06.2012