웹 개발을 위해 NHibernate를 사용하는 대부분의 친구들은 Session-Per-Request 모드를 알고 있지만 인터넷에서 이를 올바르게 사용하는 방법에 대한 예는 많지 않습니다. 그리고 이런 실수가 퍼지고 있는데..
먼저 Flyear가 작성한 "NHibernate One Session Per Request Simple Implement"이라는 글을 살펴보겠습니다.
NHibernate를 먼저 구성하는 데에는 아무런 문제가 없습니다.
<property name='current_session_context_class'>웹</property>
오류는 NHinbernateSessionFactory 클래스에 있습니다(클래스 이름이 모두 잘못됨). NHinbernateSessionFactory.GetCurrentSession은 HttpContext에 대한 작업을 포함해서는 안 됩니다. GetCurrentSession은 실제로 매우 간단해야 합니다(클래스 이름은 짧게 변경됨).
공개 봉인 클래스 NHibernateHelper
{
공개 정적 읽기 전용 ISessionFactory SessionFactory;
정적NHibernateHelper()
{
SessionFactory = 새 구성()
.구성()
.AddAssembly(/**/)
.BuildSessionFactory();
}
공개 정적 ISession GetCurrentSession()
{
SessionFactory.GetCurrentSession()을 반환합니다.
}
}
current_session_context_class를 웹으로 구성하면 NHibernate는 초기화 중에 NHibernate.Context.WebSessionContext 클래스의 인스턴스를 생성합니다. WebSessionContext 클래스의 소스 코드는 다음과 같습니다.
[직렬화 가능]
공개 클래스 WebSessionContext : MapBasedSessionContext
{
//전지
private const string SessionFactoryMapKey = "NHibernate.Context.WebSessionContext.SessionFactoryMapKey";
// 메소드
공용 WebSessionContext(ISessionFactoryImplementor 공장) : 기본(공장)
{ }
보호된 재정의 IDictionary GetMap()
{
return (HttpContext.Current.Items[SessionFactoryMapKey]를 IDictionary로);
}
보호된 재정의 void SetMap(IDictionary 값)
{
HttpContext.Current.Items[SessionFactoryMapKey] = 값;
}
}
WebSessionContext는 HttpContext를 캡슐화하는 Session-Per-Request 모드를 구현하므로 보조 클래스(NHibernateSessionFactory 또는 NHibernateHelper)에서 HttpContext를 작동할 필요가 없습니다.
WebSessionContext의 인스턴스에서 Session을 가져오기만 하면 됩니다. WebSessionContext 클래스에서 현재 ISession을 얻는 것은 매우 간단합니다. 왜냐하면 WebSessionContext는 ICurrentSessionContext 인터페이스를 구현하기 때문입니다.
공용 인터페이스 ICurrentSessionContext
{
ISession 현재세션();
}
NHibernate.Context 네임스페이스의 클래스 및 인터페이스
(참고: current_session_context_class는 각각 ManagedWebSessionContext, CallSessionContext 및 ThreadStaticSessionContext 클래스에 해당하는 Managed_web, Call, thread_static으로 구성될 수도 있습니다.)
실제 사용에서는 WebSessionContext의 CurrentSession() 메서드를 직접 호출할 필요가 없습니다. ISessionFactory가 한 단계로 Session을 얻을 수 있는 더 간단한 메서드를 제공하기 때문입니다.
공용 인터페이스 ISessionFactory: IDisposable
{
ISession GetCurrentSession();
//......
}
ISessionFactory.GetCurrentSession 메서드의 구체적인 구현에 대해 논의해 보겠습니다.
Configuration.BuildSessionFactory 메소드는 실제로 SessionFactoryImpl 클래스의 인스턴스를 반환합니다. SessionFactoryImpl의 코드 중 일부를 간략하게 살펴보겠습니다.
공개 봉인 클래스 1개 SessionFactoryImpl
2: ISessionFactoryImplementor, IMapping, ISessionFactory, IDisposable, IObjectReference
3 {
4 개인 읽기 전용 ICurrentSessionContext currentSessionContext;
5
6 공개 ISession GetCurrentSession()
7 {
8 if (this.currentSessionContext == null)
9 {
10 새로운 HibernateException이 발생합니다(
11 "CurrentSessionContext가 구성되지 않았습니다(current_session_context_class 속성 설정)!");
12}
13 return this.currentSessionContext.CurrentSession();
14}
15
16 공개 ICurrentSessionContext CurrentSessionContext
17 {
18 get { return this.currentSessionContext }
19}
20
21 개인 ICurrentSessionContext BuildCurrentSessionContext()
스물 둘 {
23 문자열 이름 = PropertiesHelper.GetString("current_session_context_class", this.properties, null);
24 문자열 str2 = 이름;
25 if (str2 != null)
26 {
27 if (str2 == "call") return new CallSessionContext(this);
28 if (str2 == "thread_static") return new ThreadStaticSessionContext(this);
29 if (str2 == "web") return new WebSessionContext(this);
30 if (str2 == "managed_web") return new ManagedWebSessionContext(this);
31}
그 외 32개
33 null을 반환합니다.
34번 시도
35 {
36 유형 유형 = ReflectHelper.ClassForName(이름);
37 반환 (ICurrentSessionContext)Environment.BytecodeProvider.ObjectsFactory
38.CreateInstance(type, new object[] { this });
39 }
40 캐치 (예외 예외)
41 {
42 log.Error("현재 세션 컨텍스트 [" + 이름 + "]"를 구성할 수 없습니다, 예외);
43 null을 반환합니다.
44}
45 }
46 //......
47 }
SessionFactoryImpl이 인스턴스화되면 BuildCurrentSessionContext() 메서드(21행)를 호출하여 currentSessionContext 필드에 값을 할당합니다. 특정 값은 구성 파일의 current_session_context_class에 의해 결정됩니다.
ISessionFactory의 GetCurrentSession()은 ICurrentSessionContext의 CurrentSession()(6행) 메서드를 호출합니다.
위의 코드는 매우 간단합니다. 모두가 이미 이해하고 있을 것입니다.
"NHibernate 단순 구현당 단일 세션" 기사에는 두 개의 부적절한 위치가 있습니다.
1. 모든 요청에 데이터베이스에 액세스하기 위해 세션이 필요한 것은 아닙니다. 기사의 Global.asax 코드는 모든 요청 시작 시 WebSessionContext.Bind()를 수행하는데, 이는 많은 세션을 낭비하게 됩니다. NHibernate의 세션은 가볍지만, 보다 합리적인 접근 방식은 시간 바인딩을 "정말로 필요로"하는 것입니다.
2. WebSessionContext.Unbind 메소드에는 ISessionFactory 인터페이스의 인스턴스가 필요하기 때문에 SessionFactory를 노출하려면 도우미 클래스(NHibernateSessionFactory 또는 NHibernateHelper)를 사용해야 합니다.
첫 번째 질문은 해결하기 쉽기 때문에 답글에 남겨서 모두와 소통해보세요.
두 번째 질문에 대해서는 다음 에세이에서 답하겠습니다.
나는 오랫동안 NHibernate를 배우지 않았고 초보자입니다. 실수가 있으면 정정해 주세요!