Die meisten Freunde, die NHibernate für die Webentwicklung verwenden, kennen den Session-Per-Request-Modus, aber es gibt nicht viele Beispiele für die korrekte Verwendung im Internet. Viele Artikel im Internet, auch im Garten, haben den gleichen Fehler gemacht. Und dieser Fehler hat sich ausgebreitet...
Schauen wir uns zunächst einen Artikel von Flyear im Garten an, „NHibernate One Session Per Request Simple Implementation“.
Es ist nichts Falsches daran, NHibernate zuerst zu konfigurieren:
<property name='current_session_context_class'>web</property>
Der Fehler liegt in der Klasse NHibernateSessionFactory (die Klassennamen sind alle falsch).
öffentliche versiegelte Klasse NHibernateHelper
{
öffentliche statische schreibgeschützte ISessionFactory SessionFactory;
staticNHibernateHelper()
{
SessionFactory = neue Konfiguration()
.Konfigurieren()
.AddAssembly(/**/)
.BuildSessionFactory();
}
öffentliche statische ISession GetCurrentSession()
{
return SessionFactory.GetCurrentSession();
}
}
Konfigurieren Sie current_session_context_class als Web, und NHibernate generiert während der Initialisierung eine Instanz der NHibernate.Context.WebSessionContext-Klasse. Der Quellcode der WebSessionContext-Klasse lautet wie folgt:
[Serialisierbar]
öffentliche Klasse WebSessionContext: MapBasedSessionContext
{
//Felder
private const string SessionFactoryMapKey = "NHibernate.Context.WebSessionContext.SessionFactoryMapKey";
// Methoden
public WebSessionContext(ISessionFactoryImplementor Factory) : Base(Factory)
{ }
protected override IDictionary GetMap()
{
return (HttpContext.Current.Items[SessionFactoryMapKey] als IDictionary);
}
protected override void SetMap(IDictionary-Wert)
{
HttpContext.Current.Items[SessionFactoryMapKey] = value;
}
}
WebSessionContext implementiert den Session-Per-Request-Modus, der HttpContext kapselt, sodass wir HttpContext nicht in unserer Hilfsklasse (NHibernateSessionFactory oder NHibernateHelper) betreiben müssen.
Wir müssen nur die Sitzung von der Instanz von WebSessionContext abrufen. Das Abrufen der aktuellen ISession aus der Klasse WebSessionContext ist recht einfach, da WebSessionContext die Schnittstelle ICurrentSessionContext implementiert:
öffentliche Schnittstelle ICurrentSessionContext
{
ISession CurrentSession();
}
Klassen und Schnittstellen im NHibernate.Context-Namespace
(Hinweis: current_session_context_class kann auch als Managed_web, Call, thread_static konfiguriert werden, entsprechend den Klassen ManagedWebSessionContext, CallSessionContext bzw. ThreadStaticSessionContext.)
Bei der tatsächlichen Verwendung müssen wir die CurrentSession()-Methode von WebSessionContext nicht direkt aufrufen, da ISessionFactory eine einfachere Methode bereitstellt, mit der wir die Sitzung in einem Schritt abrufen können:
öffentliche Schnittstelle ISessionFactory: IDisposable
{
ISession GetCurrentSession();
//............
}
Lassen Sie uns die spezifische Implementierung der ISessionFactory.GetCurrentSession-Methode besprechen:
Die Methode Configuration.BuildSessionFactory gibt tatsächlich eine Instanz der SessionFactoryImpl-Klasse zurück. Werfen wir einen kurzen Blick auf den Code von SessionFactoryImpl:
1 öffentliche versiegelte Klasse SessionFactoryImpl
2: ISessionFactoryImplementor, IMapping, ISessionFactory, IDisposable, IObjectReference
3 {
4 privater schreibgeschützter ICurrentSessionContext currentSessionContext;
5
6 öffentliche ISession GetCurrentSession()
7 {
8 if (this.currentSessionContext == null)
9 {
10 werfen Sie eine neue HibernateException(
11 „Kein CurrentSessionContext konfiguriert (legen Sie die Eigenschaft current_session_context_class fest)!“);
12}
13 return this.currentSessionContext.CurrentSession();
14}
15
16 öffentlicher ICurrentSessionContext CurrentSessionContext
17 {
18 get { return this.currentSessionContext }
19}
20
21 privater ICurrentSessionContext BuildCurrentSessionContext()
zweiundzwanzig {
23 string name = PropertiesHelper.GetString("current_session_context_class", this.properties, null);
24 string str2 = name;
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 sonst
33 null zurückgeben;
34 Versuche
35 {
36 Typ type = ReflectHelper.ClassForName(name);
37 return (ICurrentSessionContext)Environment.BytecodeProvider.ObjectsFactory
38.CreateInstance(type, new object[] { this });
39 }
40 Fang (Ausnahme Ausnahme)
41 {
42 log.Error("Der aktuelle Sitzungskontext [" + Name + "] konnte nicht erstellt werden", Ausnahme);
43 null zurückgeben;
44}
45 }
46 //......
47 }
Wenn SessionFactoryImpl instanziiert wird, ruft es die Methode BuildCurrentSessionContext() auf (Zeile 21), um dem Feld currentSessionContext einen Wert zuzuweisen. Der spezifische Wert wird durch die current_session_context_class in der Konfigurationsdatei bestimmt.
GetCurrentSession() von ISessionFactory ruft die CurrentSession()-Methode (Zeile 6) von ICurrentSessionContext auf.
Der obige Code ist recht einfach, jeder muss ihn bereits verstehen.
Im Artikel „NHibernate One Session Per Request Simple Implementation“ gibt es zwei unpassende Stellen:
1. Nicht jede Anfrage erfordert eine Sitzung, um auf die Datenbank zuzugreifen. Der Code von Global.asax im Artikel führt WebSessionContext.Bind() zu Beginn aller Anforderungen aus, wodurch viel Sitzung verschwendet wird. Obwohl die Sitzung von NHibernate leichtgewichtig ist, besteht ein vernünftigerer Ansatz darin, die Zeitbindung „wirklich zu benötigen“.
2. Da die WebSessionContext.Unbind-Methode eine Instanz der ISessionFactory-Schnittstelle erfordert, sind wir gezwungen, unsere Hilfsklasse (NHibernateSessionFactory oder NHibernateHelper) zu verwenden, um die SessionFactory verfügbar zu machen.
Die erste Frage ist einfacher zu lösen. Belassen Sie sie also in der Antwort, um mit allen zu kommunizieren.
Die zweite Frage werde ich im nächsten Aufsatz beantworten.
Ich habe NHibernate schon lange nicht mehr gelernt und bin ein Neuling. Wenn es Fehler gibt, korrigieren Sie mich bitte!