Желательная загрузка дочерней коллекции с помощью NHibernate
Я хочу загрузить корневые объекты и загружать все элементы дочерней коллекции и агрегата.
Пытались использовать SetFetchMode
в FluentNHibernate, но я получаю дубликаты в одной из дочерней коллекции, так как у меня есть глубина 3 уровня. DistinctRootEntityResultTransformer
, к сожалению, удаляет только дубликаты корней.
return Session.CreateInvoiceBaseCriteria(query, archived)
.AddOrder(new Order(query.Order, query.OrderType == OrderType.ASC))
.SetFetchMode("States", FetchMode.Eager)
.SetFetchMode("Attestations", FetchMode.Eager)
.SetFetchMode("AttestationRequests", FetchMode.Eager)
.SetFetchMode("AttestationRequests.Reminders", FetchMode.Eager)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Invoice>();
Могу ли я использовать несколько запросов или что-то подобное в архиве?
Кроме того, не приведет ли этот подход к излишне огромным наборам результатов из базы данных?
Любые предложения?
Ответы
Ответ 1
Нашел решение, но это не очень. Сначала я просматриваю все идентификаторы счетов, затем я использую их в multiquery, а затем в конце фильтрации результатов через HashedSet. Из-за большого количества элементов иногда я не мог использовать normalt Restriction.In и был вынужден отправить его как строку.
Любые предлагаемые настройки?
var criteria = Session.CreateInvoiceBaseCriteria(query, archived)
.SetProjection(Projections.Id());
var invoiceIds = criteria.List<int>();
if (invoiceIds.Count > 0)
{
var joinedIds = JoinIDs(criteria.List<int>()); // To many ids to send them as parameters.
var sql1 = string.Format("from Invoice i inner join fetch i.States where i.InvoiceID in ({0}) order by i.{1} {2}", joinedIds, query.Order, query.OrderType.ToString());
var sql2 = string.Format("from Invoice i inner join fetch i.AttestationRequests where i.InvoiceID in ({0})", joinedIds);
var sql3 = string.Format("from Invoice i inner join fetch i.Attestations where i.InvoiceID in ({0})", joinedIds);
var invoiceQuery = Session.CreateMultiQuery()
.Add(sql1)
.Add(sql2)
.Add(sql3);
var result = invoiceQuery.List()[0];
return new UniqueFilter<Invoice>((ICollection)result);
}
return new List<Invoice>();
Ответ 2
Чтобы ответить на ваш вопрос: да, это приводит к огромным результатам.
Я предлагаю:
- просто наивно пишите свои запросы, не жалуясь на выбор.
- В некоторых местах введите желаемую выборку, но только один для каждого запроса
- Если вы действительно получаете проблемы с производительностью, которые не можете решить с помощью индексов или путем повышения запросов и стратегий сопоставления, используйте свое решение с несколькими запросами.
Ответ 3
Хотя это может быть не совсем то, что вы ищете, я бы рекомендовал посмотреть на эту статью:
Ожидающая загрузка агрегата со многими дочерними коллекциями
Если вы посмотрите вокруг остальной части этого сайта, вы найдете еще больше сообщений, которые обсуждают нетерпеливую загрузку и другие замечательные вещи nHibernate.