Подтвердить что ты не робот

Желательная загрузка дочерней коллекции с помощью 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>();

Могу ли я использовать несколько запросов или что-то подобное в архиве?

Кроме того, не приведет ли этот подход к излишне огромным наборам результатов из базы данных?

Любые предложения?

4b9b3361

Ответ 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.