ObjectDisposedException сеанса NHibernate

Есть ли способ проверить, был ли сеанс удален NHibernate?

У меня есть класс-оболочка для сеанса, который имеет собственную реализацию Finalizer и IDispoable, однако, если сеанс удаляется до того, как я сам обработаю его в своем классе, я получаю исключение ObjectDisposedException.

Я действительно не хочу обертывать мой код очистки

try {
...
}
catch (ObjectDisposedException) { }

Но я не уверен в другом. Свойства Session.IsOpen и Session.IsActive, по-видимому, не предоставляют мне никакой надежной информации, чтобы подтвердить, что сеанс был удален.

Полный исходный код можно просмотреть на Сборка.


person Chris Marisic    schedule 03.02.2009    source источник


Ответы (3)


Хорошо, только что взглянул на ваш код. Я не знаю, является ли это именно проблемой, но вы вызываете End() из метода dispose разговора, который, в свою очередь, пытается повторно подключиться и удалить сеанс.. если вы явно вызвали End() до этого, вы получите что вы получаете, избегайте этого звонка. Я думаю, вам не следует беспокоиться об откате транзакции до удаления сеанса, поскольку это делается неявно. Только что взглянул, но я думаю, что мне очень нравится ваша реализация.

person Fredy Treboux    schedule 04.02.2009
comment
Вы правы, что это происходит, когда я пытаюсь повторно подключиться, поскольку в конце моих модульных тестов, где я получаю удаленное исключение, сеанс всегда isopen = true, isconnected = false. я просто не понимаю, почему свойство isopen будет истинным, когда базовое соединение удалено - person Chris Marisic; 05.02.2009
comment
Может быть, вы правы, и мне просто должно быть все равно, так как всегда кажется, что от него все равно избавляются, вы проверяли мой блог на весь деловой разговор по шаблону транзакции? dotnetchris.wordpress.com /27.01.2009/ - person Chris Marisic; 05.02.2009

Я всегда думал, что лучшей практикой с NHibernate является «сеанс на запрос», что означает, что он должен жить только внутри области «использования».

using(Session session = new Session())
{
}

Я бы предложил попытаться помешать двум людям отказаться от сеанса/разговора. Если вы управляете созданием сеансов, вы можете обернуть его в свой собственный ISession impl, который выполняет собственную проверку IsAlreadyDisposed(), чтобы предотвратить исключение. Тем не менее, учитывая, что усилия против «ожидаемого исключения» и исходный код выглядят не так уж плохо.

Я также предлагаю следить за реализацией финализатора. «Session.Is().InTransaction()» переходит в Session->Transaction, и сеанс может быть нулевым к тому времени, когда финализатор доберется до него. Не гарантируется, что навигация по управляемой связи во время финализатора будет работать.

person Quibblesome    schedule 03.02.2009
comment
Единственное место, откуда я получаю исключение, это .Reconnect, когда сеанс уже удален NH, по какой-то причине, когда он удален, он все еще может иметь Session.IsOpen = true. Это одна из самых абсурдных вещей, которые я видел, чтобы свойство Open оставалось верным даже после утилизации. - person Chris Marisic; 04.02.2009
comment
Я использую SessionFactory NH для создания сеанса. Я не уверен, как я могу использовать собственный класс сеанса, кроме загрузки исходного кода и его изменения. Однако, если бы я просто хотел это сделать, я бы просто сделал это, когда Dispose() вызывается в сеансе, который IsOpen возвращает false. - person Chris Marisic; 04.02.2009
comment
Сессия уже удалена NHibernate? В каком сценарии это происходит? Прошло некоторое время с тех пор, как я играл с NHibernate, но я не помню, чтобы он когда-либо избавлялся от сеанса. - person Quibblesome; 04.02.2009
comment
Какова ваша сессионная стратегия? Вы используете 1 сеанс для всего приложения или 1 сеанс для каждого запроса? - person Quibblesome; 04.02.2009
comment
1 сеанс на HttpSession, я использую аспектно-ориентированное программирование, чтобы позволить мне сгруппировать несколько действий в одну транзакцию. Что обычно приводит к 1 транзакции на запрос, что более эффективно, чем создание нового сеанса для каждого запроса, это преемник сеанса для каждого запроса. - person Chris Marisic; 04.02.2009
comment
У меня есть запись в блоге на эту тему: dotnetchris.wordpress.com/2009/01/27/, когда я получаю это исключение, происходит во время отключения приложения в конце моих модульных тестов, и именно здесь я пытаюсь решить эту проблему в настоящее время. - person Chris Marisic; 04.02.2009
comment
Вы пробовали пропускать финализатор? Откровенно говоря, вам не следует использовать финализаторы для автоматической очистки управляемого кода, для этого и предназначено dispose. - person Quibblesome; 05.02.2009

«Это одна из самых абсурдных вещей, которые я видел, чтобы свойство Open оставалось верным даже после утилизации».

Почему объект, который вы уже утилизировали, должен содержать достоверную информацию о своем состоянии? Вы не должны пытаться использовать удаленный сеанс, я также не знаю, где nhibernate удаляет ваш сеанс, вы уверены, что не удаляете его самостоятельно?

person Fredy Treboux    schedule 04.02.2009
comment
Моя цель - избавиться от него самостоятельно, но, по крайней мере, во время моих модульных тестов он всегда удаляется перед моим объектом, если он не удален, я хочу откатить его транзакцию, если он находится в одном, иначе явно вызовите закрыть, а затем удалить. Но проблема в том, что объект не дает возможности сказать, был ли он - person Chris Marisic; 04.02.2009