Правильная обработка переходных объектов в NHibernate - PullRequest
1 голос
/ 06 ноября 2010

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

Как только NH сохраняет сущность в одном сеансе и этот сеанс закрывается, мне нужно снова извлечь его в новом сеансе, чтобы сослаться на него в некоторых других временных объектах. Или я могу вызвать Session.Lock на новом экземпляре сеанса и сообщить NH, что эта сущность не является временной. Этот элемент никогда не должен меняться в течение срока службы приложения.

Какой предпочтительный способ использования? Есть ли другой способ сделать это?

[Изменить]

Дополнительная проблема заключается в том, что я использую шаблон Repository, а не использую NH напрямую на своем бизнес-уровне. Это означает, что мне также нужно иметь способ абстрагировать этот вызов от Session.Lock, то есть иметь метод, похожий на Session.Lock в моем интерфейсе репозитория. Это немного вонючее ИМХО.

Ответы [ 2 ]

3 голосов
/ 07 ноября 2010

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

2 голосов
/ 06 ноября 2010

По поводу первого вопроса. Если вы просто собираетесь читать сущность, вам не нужно ничего делать. Даже присвоение ее в качестве поля другой сущности не потребует от вас блокировки записи. Единственная причина, по которой вам нужно вызвать ISession.Lock, - это когда вы хотите изменить, а затем сохранить объект.

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

Если сущность все еще создает вам проблемы в этих обстоятельствах, вы можете добавить Load в свой репозиторий. Вы можете подключить это к ISession.Load. Load создает пустой прокси для сущности, не обращаясь к базе данных. Этот объект является частью сеанса, с которым объект загружен, и может использоваться для назначения свойств других объектов. Преимущество этого подхода в том, что он намного чище и его легко дразнить с помощью модульного тестирования.

По второму вопросу. Да, вы правы, что пахнет ISession.Lock в хранилище. Опять же, когда вам не нужно мутировать сущность, вам не нужно беспокоиться об этом. Но когда вы, ну, вы действительно должны подумать о том, чтобы просто перезагрузить сущность из хранилища и поработать над ней. Я знаю, что это не так оптимально, как могло бы быть, но оно спасает вас от множества очень странных кодов, особенно в ваших модульных тестах.

И последнее. Я понимаю, что вы говорите о сущности, которая будет жить в течение длительного времени (возможно, полного времени выполнения приложения). У вас есть примерно три категории жизни: 1. навсегда, 2. долго и 3. коротко. Причина, по которой я упоминаю об этом, заключается в том, что не раз проблемы с объектами, имеющими «длинное» время жизни, могли просто оставаться подключенными к сеансу с таким же временем жизни. Нет проблем в том, чтобы иметь живой сеанс, скажем, 5 или 10 минут (время, когда пользователь вводит данные в форму). Одно это избавит большинство людей от многих проблем.

Еще одно примечание: взгляните на NHibernateUtil и NHibernateProxyHelper. Эти классы могут помочь вам принудительно загрузить сущности и дочерние коллекции.

...