Как добиться загрузки ассоциаций без дублирования в NHibernate?

Мне нужно загрузить список очень больших объектов с таким количеством детей и детей детей. Каков наилучший подход?

Я использую базу данных Oracle 11g, и я написал метод ниже, но это приводит к декартовому продукту (дублированные результаты):

 public IList<ARNomination> GetByEventId(long eventId)
        {
            var session = this._sessionFactory.Session;

            var nominationQuery = session.Query<ARNomination>().Where(n => n.Event.Id == eventId);

            using (var trans = session.Transaction)
            {
                trans.Begin();

                // this will load the Contacts in one statement
                nominationQuery
                    .FetchMany(n => n.Contacts)
                    .ToFuture();

                // this will load the CustomAttributes in one statement
                nominationQuery
                    .FetchMany(n => n.CustomAttributes)
                    .ToFuture();

                // this will load the nominations but joins those two tables in one statement which results in cartesian product
                nominationQuery
                    .FetchMany(n => n.CustomAttributes)
                    .FetchMany(n => n.Contacts)
                    .ToFuture();

                trans.Commit();
            }

            return nominationQuery.ToList();
        }

2 ответа

Получение коллекций - сложная операция. У него много побочных эффектов (как вы поняли, когда собрано больше коллекций). Но даже при получении одной коллекции мы загружаем много дублированных строк.

В общем, для загрузки коллекций я бы предложил использовать пакетную обработку. Это выполнит больше запросов SQL... но не так много, и, что более важно, вы можете сделать пейджинг в корневом списке ARNomination,

Смотри: 19.1.5. Используя пакетную загрузку, вы можете найти более подробную информацию.

Вы должны пометить свои коллекции и / или объекты с атрибутом batch-szie="25",

XML:

<bag name="Contacts" ... batch-size="25">
...

свободно:

HasMany(x => x.Contacts)
  ...
  .BatchSize(25)

Пожалуйста, проверьте несколько аргументов здесь:

Я согласен с @RadimKöhler, как только вы захотите загрузить более одной коллекции, тогда всегда возникает декартово произведение. Для выбора подходящего размера партии я бы выбрал такой же, как page size как он чувствует себя хорошо... (нет доказательств, почему, хотя)

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

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

Другие вопросы по тегам