#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 есть кэшированная копия страницы .