Стремление загружать дочернюю коллекцию с помощью NHibernate - PullRequest
24 голосов
/ 02 июня 2009

Я хочу загрузить корневые объекты и стремиться загрузить все дочерние элементы коллекции и агрегирования.

Я пытался использовать 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>();

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

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

Есть предложения?

Ответы [ 3 ]

8 голосов
/ 05 июня 2009

Нашел решение, но это не красиво. Сначала я нахожу все идентификаторы счетов, затем использую их в мультизапросе, а затем в конце фильтрую результаты через 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 голосов
/ 21 октября 2009

Чтобы ответить на ваш вопрос: да, это приводит к огромным наборам результатов.

Я предлагаю:

  • просто наивно пишите свои запросы, не стремясь получить
  • В определенных местах ставить активные выборки, но только по одному на запрос
  • если у вас действительно возникают проблемы с производительностью, которые вы не можете решить с помощью индексов или улучшенных запросов и стратегий отображения, используйте свое решение с несколькими запросами.
0 голосов
/ 02 июня 2009

Хотя это может быть не совсем то, что вы ищете, я бы порекомендовал посмотреть на эту статью:

Агрегат загрузки с большим количеством дочерних коллекций

Если вы осмотрите остальную часть этого сайта, вы найдете еще больше постов, в которых обсуждается стремительная загрузка и другие замечательные вещи nHibernate.

...