Создание и получение связанных сопоставлений в NHibernate
Скажем, у меня есть два постоянных класса Cat
а также Hat
, Давайте представим, что отношения между ними двунаправлены один-ко-многим, так как в кошке может быть много разных шляп, и мы можем пройти отображение в обоих направлениях. Чтобы создать связь между экземплярами каждого класса, я должен быть в состоянии и исправить меня, если я ошибаюсь, сделать следующее:
Cat whiskers = new Cat();
Hat redHat = new Hat();
redHat.Id = 1; // normally assigned by generator but this makes example more explicit
whiskers.Hats.Add(redHat);
catService.Save(whiskers);
hatService.Save(redHat);
Имея это в виду, не должен ли я получить Cat, который связан с redHat, выполнив следующие действия?
Hat hat = hatService.FindById(1); // redHat has Id 1
Cat cat = hat.Cat; // cat should be whiskers
К сожалению, когда я пытаюсь использовать эту технику, в последней строке cat появляется как нулевой объект. Я предполагаю, что что-то упустил в своем отображении один-ко-многим в Cat.hbm.xml, или, по крайней мере, я надеюсь, что это что-то такое простое. Вот как это выглядит в настоящее время:
<set name="Hats" inverse="true">
<key column="Id"/>
<one-to-many class="Hat"/>
</set>
У меня нет сопоставления в Hat.hbm.xml, так как добавление одного привело к ошибке "дублирование сопоставления". Я прочитал документацию Hibernate по сопоставлениям ассоциаций, но все еще не могу заставить это работать. Что я делаю неправильно?
Полное отображение файлов ниже:
Cat.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Domain"
namespace="Domain">
<class name="Cat" table="cats" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<set name="Hats" inverse="true">
<key column="Id"/>
<one-to-many class="Hat"/>
</set>
</class>
</hibernate-mapping>
Hat.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Domain"
namespace="Domain">
<class name="Hat" table="hats" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
</class>
</hibernate-mapping>
редактировать
Я считаю, что проблема заключалась в том, что я не инициализировал ISet<Hat>
значение в классе Cat. Однако я столкнулся с новой проблемой. Когда я пытаюсь получить доступ к ассоциациям, я получаю эту ошибку:
Could not initialize proxy - no Session.
Я подумал, что этого легко избежать, если бы я создал метод в моем DAO, где я мог бы обернуть его в сеанс, как это:
public Cat GetRelatedCat(Hat hat)
{
Cat cat;
using (ISession session = HibernateUtil.GetSessionFactory().OpenSession())
{
cat = hat.Cat;
}
return cat;
}
Это приводит к той же ошибке "без сеанса". Я в тупике.
2 ответа
Я решил проблему, создав SessionManager, который позволяет мне открывать сеанс, выполнять любые транзакции и получать доступ к любым прокси-серверам коллекции в одноэлементном сеансе, а затем закрывать сеанс.
Вам нужно добавить запись "многие к одному" в вашем hat.hbm. Я думаю, что должно работать.
Тогда вы должны установить обе стороны ассоциации
whiskers.Hats.Add(RedHat);
redHat.Cat = усы;
Я думаю, что это должно заставить ваш образец работать.
Причина вашей проблемы "без сеанса" заключается в том, что прокси-сервер коллекции работает только с сеансом, с которым он был создан. Так что в вашем примере это работает только с сеансом, который создал ваш экземпляр Hat. Можно подключить прокси-сервер к другому сеансу, но обычно это не рекомендуется, поскольку он имеет сложные последствия для границ транзакций и согласованности данных.