Свободное владение NHibernate и несколькими ключевыми столбцами

#c# #nhibernate #fluent-nhibernate

#c# #nhibernate #свободное владение-nhibernate

Вопрос:

У меня есть объект User, у которого есть свойство IList. Сопоставление для этого выглядит следующим образом:

         HasMany(x => x.Forms) 
            .Cascade.None() 
            .AsBag().KeyColumn("Supervisor") 
            .Key(key => key.Not.Update()) 
            .PropertyRef("Email"); 
  

Теперь у меня есть новый запрос функции, который, по сути, добавляет еще один
Ключевая колонка, которая также должна быть заполнена в этом свойстве. По сути,
у каждой формы может быть «Супервизор» и «Альтернатива», и мне это нужно
свойство для заполнения любых форм, где User.Email равно либо
один (Формы ПРИНАДЛЕЖАТ пользователю, ЕСЛИ User.Email == Form.Supervisor OR User.Email == Form.Alternate ).

Есть ли способ сделать это? Простое добавление другой KeyColumn спецификации просто переопределяет предыдущую, а добавление ключей с помощью Keys() метода, похоже, не позволяет использовать несколько ключевых столбцов, как я хочу… Я ищу способ по существу сообщить ему, что эта связь должна быть найдена с помощью WHERE Superviser = Email OR Alternate = Email , но, похоже, это не поддерживает это OR предложение…

Мой другой вариант — по сути, дублировать это сопоставление, но для «альтернативного» в другом свойстве, а затем объединить коллекции вместе в моем коде, использующем, но я хотел посмотреть, достаточно ли NHibernate умен, чтобы это стало возможным…

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

Ответ №1:

Насколько мне известно, no — NHibernate не поддерживает этот необычный тип объединения. Я бы подошел к этому точно так, как вы сказали. Используйте две коллекции — User.SupervisorForms и User.AlternateForms , затем объедините их позже, возможно, используя для этого Concat метод LINQ. Вы могли бы определить свойство для выполнения этой конкатенации за вас:

 public virtual IEnumerable<Form> Forms
{
    get { return SupervisorForms.Concat(AlternateForms); }
}
  

Если вы хотите загрузить User полностью инициализированную Forms коллекцию за один цикл обращения к базе данных, вы можете использовать этот подход из раздела «Улучшение производительности — множественный запрос» документации NHibernate:

 User user = s.CreateMultiQuery()
    .Add("select u from User u left join fetch u.SupervisorForms where u.Id = :id")
    .Add("select u from User u left join fetch u.AlternateForms where u.Id = :id")
    .SetInt32("id", 123)
    .UniqueResult<User>();
  

В этом коде используются CreateMultiQuery() и HQL — но подход должен работать так же хорошо с выбранным вами синтаксисом пакетной обработки запросов: CreateMultiQuery() , CreateMultiCriteria() или Future() / FutureValue() .

Комментарии:

1. Это именно то, что я в конечном итоге сделал, поскольку мои поиски в базе NHibernate ничего не вернули. Противоречит моему желанию максимально ограничить количество обращений к SQL (это, по сути, удваивает их), но это работает и не привело к значительному снижению производительности.

2. Добавлена информация о предварительной загрузке этих двух коллекций за один цикл в базу данных. Примечание — NHForge, похоже, в данный момент не работает, поэтому ссылка не работает, но у Google есть кэшированная копия страницы .