يعرف معظم الأصدقاء الذين يستخدمون NHibernate لتطوير الويب وضع الجلسة لكل طلب، ولكن لا توجد أمثلة كثيرة لكيفية استخدامه بشكل صحيح على الإنترنت، وقد ارتكبت العديد من المقالات على الإنترنت، بما في ذلك في الحديقة، نفس الخطأ. وهذا الخطأ انتشر..
دعونا نلقي نظرة أولاً على مقال بقلم Flyear في الحديقة، "التنفيذ البسيط لجلسة واحدة لكل طلب من NHibernate".
لا حرج في تكوين NHibernate أولاً:
<property name='current_session_context_class'>الويب</property>
الخطأ موجود في فئة NHinbernateSessionFactory (أسماء الفئات كلها خاطئة. يجب ألا يتضمن GetCurrentSession العمليات على HttpContext. يرجى الاطلاع على (تم تغيير اسم الفئة إلى NHibernateHelper، باختصار):
فئة مختومة عامة NHibernateHelper
{
الجمهور الثابت للقراءة فقط ISessionFactory SessionFactory؛
ثابتNHibernateHelper()
{
SessionFactory = تكوين جديد ()
.تكوين ()
.AddAssembly(/**/)
.BuildSessionFactory();
}
ISession العامة الثابتة GetCurrentSession()
{
إرجاع SessionFactory.GetCurrentSession();
}
}
قم بتكوين current_session_context_class كالويب، وسيقوم NHibernate بإنشاء مثيل لفئة NHibernate.Context.WebSessionContext أثناء التهيئة، الكود المصدري لفئة WebSessionContext هو كما يلي:
[قابل للتسلسل]
WebSessionContext للفئة العامة: MapBasedSessionContext
{
//الحقول
سلسلة const الخاصة SessionFactoryMapKey = "NHibernate.Context.WebSessionContext.SessionFactoryMapKey";
// طُرق
WebSessionContext العام (مصنع ISessionFactoryImplementor): القاعدة (المصنع)
{ }
تجاوز محمي IDictionary GetMap ()
{
return (HttpContext.Current.Items[SessionFactoryMapKey] كمعرف)؛
}
تجاوز محمي SetMap (قيمة معرفية)
{
HttpContext.Current.Items[SessionFactoryMapKey] = value;
}
}
ينفذ WebSessionContext وضع الجلسة لكل طلب، والذي يتضمن HttpContext، لذلك لا نحتاج إلى تشغيل HttpContext في فئتنا المساعدة (NHibernateSessionFactory أو NHibernateHelper).
نحتاج فقط إلى الحصول على الجلسة من مثيل WebSessionContext. يعد الحصول على ISession الحالي من فئة WebSessionContext أمرًا بسيطًا للغاية، لأن WebSessionContext يطبق واجهة ICurrentSessionContext:
الواجهة العامة ICurrentSessionContext
{
ISession CurrentSession();
}
الفئات والواجهات في مساحة الاسم NHibernate.Context
(ملاحظة: يمكن أيضًا تكوين current_session_context_class على أنه Managed_web، وCall، وthread_static، المتوافق مع الفئات ManagedWebSessionContext، وCallSessionContext، وThreadStaticSessionContext على التوالي)
في الاستخدام الفعلي، لا نحتاج إلى استدعاء طريقة CurrentSession() مباشرة لـ WebSessionContext، لأن ISessionFactory يوفر طريقة أبسط تسمح لنا بالحصول على الجلسة في خطوة واحدة:
الواجهة العامة ISessionFactory: IDisposable
{
ISession GetCurrentSession();
//......
}
دعونا نناقش التنفيذ المحدد لطريقة ISessionFactory.GetCurrentSession:
يقوم الأسلوب Configuration.BuildSessionFactory في الواقع بإرجاع مثيل لفئة SessionFactoryImpl دعنا نلقي نظرة سريعة على بعض التعليمات البرمجية الخاصة بـ SessionFactoryImpl:
1 فئة عامة مختومة SessionFactoryImpl
2: ISessionFactoryImplementor، IMapping، ISessionFactory، IDisposable، IObjectReference
3 {
4 خاص للقراءة فقط ICurrentSessionContextcurrentSessionContext;
5
6 ISession العامة GetCurrentSession()
7 {
8 إذا (this.currentSessionContext == null)
9 {
10 رمي HibernateException (
11 "لم يتم تكوين CurrentSessionContext (قم بتعيين الخاصية current_session_context_class)!");
12}
13 إرجاع this.currentSessionContext.CurrentSession();
14}
15
16.ICurrentSessionContext العام CurrentSessionContext
17 {
18 احصل على {return this.currentSessionContext}؛
19}
20
21 خاص ICurrentSessionContext BuildCurrentSessionContext()
إثنان وعشرون {
23 string name = PropertiesHelper.GetString("current_session_context_class", this.properties, null);
24 سلسلة str2 = الاسم؛
25 إذا (str2 != فارغة)
26 {
27 if (str2 == "call") بإرجاع CallSessionContext الجديد(this);
28 إذا قام (str2 == "thread_static") بإرجاع ThreadStaticSessionContext(this);
29 if (str2 == "web") تُرجع WebSessionContext الجديد(this);
30 إذا قام (str2 == "managed_web") بإرجاع ManagedWebSessionContext(this);
31}
32 آخر
33 إرجاع فارغ؛
34 محاولة
35 {
36 اكتب type = ReflectHelper.ClassForName(name);
37 العودة (ICurrentSessionContext)Environment.BytecodeProvider.ObjectsFactory
38.CreateInstance(type, new object[] { this });
39 }
40 صيدًا (استثناء استثنائي)
41 {
42 log.Error("غير قادر على إنشاء سياق الجلسة الحالية [" + name + "]"، استثناء)؛
43 إرجاع فارغ؛
44}
45 }
46 //......
47 }
عندما يتم إنشاء مثيل SessionFactoryImpl، فإنه يستدعي طريقة BuildCurrentSessionContext() (السطر 21) لتعيين قيمة لحقل currentSessionContext، ويتم تحديد القيمة المحددة بواسطة current_session_context_class في ملف التكوين.
يستدعي GetCurrentSession() الخاص بـ ISessionFactory أسلوب CurrentSession() الخاص بـ ICurrentSessionContext (السطر 6).
الكود أعلاه بسيط للغاية، ويجب على الجميع فهمه بالفعل.
يوجد مكانان غير مناسبين في المقالة "NHibernate One Session Per Request Simple Implementation":
1. لا يتطلب كل طلب جلسة للوصول إلى قاعدة البيانات. يقوم كود Global.asax الموجود في المقالة بتنفيذ WebSessionContext.Bind() في بداية جميع الطلبات، مما سيضيع الكثير من الجلسة. على الرغم من أن جلسة NHibernate خفيفة الوزن، إلا أن الطريقة الأكثر منطقية هي "الحاجة حقًا" إلى ربط الوقت.
2. نظرًا لأن أسلوب WebSessionContext.Unbind يتطلب مثيلًا لواجهة ISessionFactory، فإننا مضطرون إلى استخدام فئة المساعد الخاصة بنا (NHibernateSessionFactory أو NHibernateHelper) لكشف SessionFactory.
السؤال الأول أسهل في الحل، اتركه في الرد للتواصل مع الجميع.
سأجيب على السؤال الثاني في المقال القادم.
لم أتعلم NHibernate منذ فترة طويلة وأنا مبتدئ. إذا كان هناك أي أخطاء، يرجى تصحيح لي!