2009-07-08 2 views
0

Я только что начал использовать NHibernate, и у меня есть некоторые проблемы, которые я не уверен, как правильно решать.Сессии NHibernate - какой общий способ обработки сеансов в приложениях Windows?

Я начал создавать общий репозиторий, содержащий CUD и пару методов поиска. Каждый из этих методов открывает отдельный сеанс (и транзакцию, если необходимо) во время операций (ов) БД. Проблема при выполнении этого (насколько я могу судить) заключается в том, что я не могу воспользоваться ленивой загрузкой связанных коллекций/объектов.

Поскольку почти любое отношение сущности имеет .Not.LazyLoad() при свободном сопоставлении, это приводит к загрузке всей базы данных, когда я запрашиваю список всех объектов данного типа.

Поправьте меня, если я ошибаюсь, потому что я до сих пор полный новичок, когда дело доходит до NHibernate :)

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


Часть кода репозитория:

public T GetById(int id) 
{ 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     return session.Get<T>(id); 
    } 
} 

Использование хранилища, чтобы получить человек

var person = m_PersonRepository.GetById(1); // works fine 

var contactInfo = person.ContactInfo; // Throws exception with message: 

// failed to lazily initialize a collection, no session or session was closed 

ответ

3

Ваш вопрос фактически сводится к объекту кэширования и повторного использования. Если вы загружаете объект Foo из одного сеанса, можете ли вы его удерживать, а затем в более поздний момент времени ленивая загрузка его свойства Bar?

Каждый экземпляр ISession предназначен для представления единицы работы и поставляется с кешем первого уровня, который позволит вам получить объект несколько раз в пределах этой единицы работы, но только с одним ударом базы данных. Он не является потокобезопасным и определенно не должен использоваться как статический объект в приложении WinForms.

Если вы хотите использовать объект, когда сеанс, в котором он был загружен, был удален, вам необходимо связать его с новым сеансом, используя Session.SaveOrUpdate (object) или Session.Update (object).

Все это объяснено в chapter 10 of the Hibernate documentation.

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

Редактировать в свете кода размещена

Ваше использование сеанса на неправильном уровне - вы используете его для одной базы данных получить, а не единицы работы. В этом случае ваш метод GetById должен принять в сеансе, который он использует, и экземпляр сеанса должен управляться на более высоком уровне. В качестве альтернативы, ваш класс PersonRepository должен управлять сеансом, если вы предпочитаете, и вы должны создавать экземпляр и размещать объект такого типа для каждой единицы работы.

public T GetById(int id) 
{ 
    return m_session.Get<T>(id); 
} 

using (var repository = new PersonRepository()) 
{ 
    var person = repository.GetById(1); 
    var contactInfo = person.ContactInfo; 
} // make sure the repository Dispose method disposes the session. 

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

+0

Спасибо за ваш ответ. Я прочитал главу из документации, но я до сих пор не совсем понимаю, что вы подразумеваете во втором предложении. Вы имеете в виду, что мне нужно держать сессию, если мне нужно получить доступ к ленивым загруженным свойствам? Я добавлю часть моего кода репозитория на вопрос. – l3dx

+0

Конечно - добавьте некоторый контекст к вопросу, и я рассмотрю его более конкретно в ответе. –

+0

Ницца, спасибо большое! +1 Я буду реорганизовывать мой репозиторий тогда :) Мое понимание состоит в том, что материал session/db должен быть «удален» от реального приложения, поэтому, если я дополнительно удалю его из репозитория, где бы я его разместил? – l3dx

Смежные вопросы