مقدمة
في بيئة عديمة الحالة مثل تطبيق الويب، ليس لفهم مفهوم حالة الجلسة أي معنى حقيقي. ومع ذلك، تعتبر الإدارة الفعالة للحالة ميزة ضرورية لمعظم تطبيقات الويب. يوفر Microsoft ASP.NET، بالإضافة إلى العديد من بيئات البرمجة الأخرى من جانب الخادم، طبقة تجريد تسمح للتطبيقات بتخزين البيانات المستمرة على أساس كل مستخدم وكل تطبيق.
من المهم ملاحظة أن حالة جلسة تطبيق الويب هي البيانات التي يقوم التطبيق بتخزينها مؤقتًا واستردادها عبر طلبات مختلفة. تمثل الجلسة كافة الطلبات التي يرسلها المستخدم أثناء اتصاله بالموقع، وحالة الجلسة هي مجموعة البيانات المستمرة التي تم إنشاؤها واستهلاكها من قبل المستخدم أثناء الجلسة. حالة كل جلسة مستقلة عن بعضها البعض وتتوقف عن الوجود عند انتهاء جلسة المستخدم.
لا تحتوي حالة الجلسة على أي مراسلات مع أي من الكيانات المنطقية التي تشكل بروتوكول HTTP ومواصفاته. الجلسات عبارة عن طبقة تجريد تم إنشاؤها بواسطة بيئات التطوير من جانب الخادم مثل ASP وASP.NET التقليدي. تعتمد الطريقة التي يعرض بها ASP.NET حالة الجلسة وكيفية تنفيذ حالة الجلسة داخليًا على البنية الأساسية للنظام الأساسي. لذلك، يقوم ASP وASP.NET التقليدي بتنفيذ حالة الجلسة بطرق مختلفة تمامًا، ومن المتوقع إجراء المزيد من التحسينات والتحسينات في الإصدار التالي من ASP.NET.
تتناول هذه المقالة كيفية تنفيذ حالة الجلسة في ASP.NET 1.1 وكيفية تحسين إدارة حالة الجلسة في تطبيقات الويب المُدارة.
نظرة عامة على حالة جلسة ASP.NET
حالة الجلسة ليست جزءًا من البنية التحتية لـ HTTP. أي أنه يجب أن يكون هناك مكون هيكلي يربط حالة الجلسة بكل طلب وارد. يمكن لبيئة التشغيل (ASP أو ASP.NET التقليدية) قبول كلمات رئيسية مثل الجلسة واستخدامها للإشارة إلى كتلة البيانات المخزنة على الخادم. لحل الاستدعاءات إلى كائن الجلسة بنجاح، يجب أن تضيف بيئة وقت التشغيل حالة الجلسة إلى سياق الاستدعاء للطلب الذي تتم معالجته. تختلف كيفية القيام بذلك بين الأنظمة الأساسية، ولكنها أساسية لتطبيقات الويب ذات الحالة.
في ASP التقليدي، يتم تنفيذ حالة الجلسة ككائنات COM ذات ترابط حر موجودة في مكتبة asp.dll. (هل أنت فضولي؟ إن CLSID لهذا الكائن هو في الواقع D97A6DA0-A865-11cf-83AF-00A0C90C2BD8.) يقوم هذا الكائن بتخزين البيانات المنظمة كمجموعة من أزواج الاسم/القيمة. يمثل العنصر النائب "الاسم" المفتاح المستخدم لاسترداد المعلومات، بينما يمثل العنصر النائب "القيمة" ما تم تخزينه في حالة الجلسة. يتم تجميع أزواج الاسم/القيمة حسب معرف الجلسة بحيث يرى كل مستخدم فقط أزواج الاسم/القيمة التي قام بإنشائها.
في ASP.NET، تكون واجهة البرمجة لحالة الجلسة هي نفسها تقريبًا في ASP التقليدي. لكن تطبيقاتها الأساسية مختلفة تمامًا، فالأولى أكثر مرونة وقابلة للتطوير ولديها قدرات برمجية أقوى من الأخيرة. قبل أن نتعمق في حالة جلسة ASP.NET، دعنا نراجع بإيجاز بعض القدرات الهيكلية للبنية التحتية لجلسة ASP.NET.
في ASP.NET، يتم إرسال أي طلب HTTP وارد عبر وحدة HTTP النمطية. يمكن لكل وحدة تصفية وتعديل الكمية الكبيرة من المعلومات التي يحملها الطلب. تسمى المعلومات المرتبطة بكل طلب "سياق الاستدعاء" الذي يمثله كائن HttpContext في البرمجة. لا ينبغي لنا أن نفكر في سياق الطلب باعتباره حاوية أخرى لمعلومات الحالة، على الرغم من أن مجموعة العناصر التي يوفرها هي مجرد حاوية بيانات. يختلف كائن HttpContext عن كافة كائنات الحالة الأخرى (على سبيل المثال، الجلسة والتطبيق وذاكرة التخزين المؤقت) حيث أن له عمرًا محدودًا يتجاوز الوقت المطلوب لمعالجة الطلب. عندما يمر طلب عبر سلسلة من وحدات HTTP المسجلة، سيحتوي كائن HttpContext الخاص به على مرجع لكائن الحالة. عندما يمكن معالجة الطلب أخيرًا، يرتبط سياق الاستدعاء المرتبط بالجلسة المحددة (الجلسة) وكائنات الحالة العامة (التطبيق وذاكرة التخزين المؤقت).
وحدة HTTP المسؤولة عن تحديد حالة جلسة كل مستخدم هي SessionStateModule. تم تصميم هيكل هذه الوحدة بناءً على واجهة IHttpModule، التي توفر عددًا كبيرًا من الخدمات المتعلقة بحالة الجلسة لتطبيقات ASP.NET. يتضمن إنشاء معرفات الجلسة، وإدارة الجلسة بدون ملفات تعريف الارتباط، واسترداد بيانات الجلسة من موفري الحالة الخارجيين، وربط البيانات بسياق الاتصال الخاص بالطلب.
لا تقوم وحدة HTTP بتخزين بيانات الجلسة داخليًا. يتم حفظ حالة الجلسة دائمًا في مكون خارجي يسمى "موفر الحالة". يقوم موفر الحالة بتغليف بيانات حالة الجلسة بالكامل ويتواصل مع الأجزاء الأخرى من خلال أساليب واجهة IStateClientManager. تستدعي وحدة HTTP الخاصة بحالة الجلسة الأساليب الموجودة على هذه الواجهة لقراءة حالة الجلسة وحفظها. يدعم ASP.NET 1.1 ثلاثة موفري حالة مختلفين، كما هو موضح في الجدول 1.
الجدول 1:وصف موفر
موفر حالة العميل
تظل قيم جلسة InProc كائنات نشطة في ذاكرة العملية المنفذة لـ ASP.NET (aspnet_wp.exe أو w3wp.exe في Microsoft® Windows Server® 2003). هذا هو الخيار الافتراضي.
يتم إجراء تسلسل لقيم جلسة StateServer وتخزينها في الذاكرة في عملية منفصلة (aspnet_state.exe). يمكن أيضًا تشغيل العملية على أجهزة كمبيوتر أخرى.
يتم إجراء تسلسل لقيم جلسة SQLServer وتخزينها في جداول Microsoft® SQL Server®. يمكن تشغيل مثيلات SQL Server محليًا أو عن بعد.
تقرأ وحدة HTTP لحالة الجلسة موفر الحالة المحدد حاليًا من قسم
تقوم وحدة HTTP بإلغاء تسلسل قيمة الجلسة في بداية الطلب، مما يجعلها كائنات القاموس (في الواقع، يتم الوصول إلى الكائنات من النوع HttpSessionState) برمجيًا من خلال خاصية الجلسة التي تعرضها الفئات (على سبيل المثال، HttpContext وPage). ويستمر الارتباط حتى انتهاء الطلب. إذا اكتمل الطلب بنجاح، فسيتم إجراء تسلسل لجميع قيم الحالة إلى موفر الحالة والمتاح للطلبات الأخرى،
يوضح الشكل 1 الاتصال بين صفحة ASP.NET المطلوبة وقيم الجلسة، ويرتبط الكود الذي تستخدمه كل صفحة بسمة الجلسة في فئة الصفحة نفس ما هو الحال مع ASP التقليدية.
الشكل 1: بنية حالة الجلسة في ASP.NET 1.1
القيمة الفعلية لحالة الجلسة مقفلة للوقت المطلوب لإكمال الطلب. تتم إدارة هذا القفل داخليًا بواسطة وحدة HTTP ويستخدم لمزامنة الوصول إلى حالة الجلسة.
تعمل وحدة حالة الجلسة على إنشاء مثيل لموفر حالة التطبيق وتهيئته بالمعلومات المقروءة من ملف web.config. بعد ذلك، سيواصل كل مزود عمليات التهيئة الخاصة به. اعتمادًا على نوع الموفر، ستختلف عمليات التهيئة بشكل كبير. على سبيل المثال، سيقوم مدير حالة SQL Server بفتح اتصال بقاعدة بيانات معينة، بينما سيقوم مدير خارج العملية بالتحقق من منفذ TCP المحدد. من ناحية أخرى، سيقوم مدير حالة InProc بتخزين مرجع إلى وظيفة رد الاتصال. يتم تنفيذ هذا الإجراء عند إزالة عنصر من ذاكرة التخزين المؤقت واستخدامه لتشغيل حدث Session_OnEnd الخاص بالتطبيق.
الوصول المتزامن إلى حالة الجلسة
ماذا يحدث عندما تقوم صفحة ويب بإجراء اتصال بسيط وبديهي للغاية لخاصية الجلسة؟ يتم تنفيذ العديد من العمليات في الخلفية، كما هو موضح في التعليمات البرمجية المرهقة التالية:
int siteCount = Convert.ToInt32(Session["Counter"]);
يصل الكود أعلاه فعليًا إلى قيمة الجلسة التي أنشأتها وحدة HTTP في الذاكرة المحلية يقرأ البيانات من مزود حالة محدد (انظر الشكل 1). ماذا يحدث إذا حاولت الصفحات الأخرى أيضًا الوصول إلى حالة الجلسة بشكل متزامن؟ في هذه الحالة، قد يتوقف الطلب الحالي عن معالجة البيانات غير المتناسقة أو القديمة. لتجنب ذلك، ستنفذ وحدة حالة الجلسة آلية قفل القارئ/الكاتب وقائمة الانتظار للوصول إلى قيم الحالة. ستحتفظ الصفحات التي تتمتع بأذونات الكتابة في حالة الجلسة بقفل الكاتب لتلك الجلسة حتى ينتهي الطلب.
يمكن للصفحة أن تطلب إذن الكتابة لحالة الجلسة عن طريق تعيين خاصية EnableSessionState لتوجيه @Page إلى true. (هذا هو الإعداد الافتراضي). ومع ذلك، يمكن أن يكون للصفحة أيضًا حق الوصول للقراءة فقط إلى حالة الجلسة، على سبيل المثال، عند تعيين الخاصية EnableSessionState إلى ReadOnly. في هذه الحالة، ستحتفظ الوحدة بقفل القارئ لتلك الجلسة حتى ينتهي طلب تلك الصفحة. ونتيجة لذلك سوف تحدث القراءات المتزامنة.
إذا قام طلب الصفحة بتعيين قفل للقارئ، فلن تتمكن الطلبات المتزامنة الأخرى في نفس الجلسة من تحديث حالة الجلسة، ولكنها ستكون قادرة على القراءة على الأقل. أي أنه إذا كان طلب القراءة فقط قيد المعالجة حاليًا لجلسة ما، فسيكون لطلب القراءة فقط المعلق أولوية أعلى من الطلب الذي يتطلب الوصول الكامل. إذا قام طلب صفحة بتعيين قفل كاتب لحالة الجلسة، فسيتم حظر جميع الصفحات الأخرى بغض النظر عما إذا كانت تريد قراءة المحتوى أو كتابته. على سبيل المثال، إذا حاول إطاران الكتابة إلى الجلسة في نفس الوقت، فيجب أن ينتظر إطار واحد حتى ينتهي الإطار الآخر قبل أن يتمكن من الكتابة.
مقارنة موفري الحالة
بشكل افتراضي، تقوم تطبيقات ASP.NET بتخزين حالة الجلسة في ذاكرة العملية المنفذة، وتحديدًا في فتحة مخصصة لكائن ذاكرة التخزين المؤقت. عند تحديد وضع InProc، يتم تخزين حالة الجلسة في فتحات داخل كائن ذاكرة التخزين المؤقت. تم وضع علامة على هذه الفتحة على أنها فتحة خاصة ولا يمكن الوصول إليها برمجيًا. بمعنى آخر، إذا قمت بتعداد كافة العناصر الموجودة في ذاكرة التخزين المؤقت لبيانات ASP.NET، فلن يتم إرجاع أي كائنات مشابهة لحالة جلسة العمل المحددة. توفر كائنات ذاكرة التخزين المؤقت نوعين من الفتحات: الفتحات الخاصة والفتحات العامة. يمكن للمبرمجين إضافة الفتحات العامة والتعامل معها، ولكن لا يمكن استخدام الفتحات الخاصة إلا بواسطة النظام (على وجه التحديد، الفئات المحددة في جزء system.web).
تشغل حالة كل جلسة نشطة فتحة مخصصة في ذاكرة التخزين المؤقت. تتم تسمية الفتحة بناءً على معرف الجلسة، وقيمتها هي مثيل لفئة داخلية غير معلنة تسمى SessionStateItem. يحصل موفر حالة InProc على معرف الجلسة ويسترد العنصر المقابل في ذاكرة التخزين المؤقت. يتم بعد ذلك إدخال محتويات كائن SessionStateItem في كائن قاموس HttpSessionState ويمكن الوصول إليها بواسطة التطبيق من خلال خاصية الجلسة. لاحظ أن هناك خطأ في ASP.NET 1.0 يجعل الفتحات الخاصة لكائن ذاكرة التخزين المؤقت قابلة للتعداد برمجيًا. إذا قمت بتشغيل التعليمة البرمجية التالية ضمن ASP.NET 1.0، فستتمكن من تعداد العناصر المقابلة للكائنات الموجودة في كل حالة جلسة عمل نشطة حاليًا.
foreach (عنصر إدخال القاموس في ذاكرة التخزين المؤقت)
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
تم حل هذا الخطأ في ASP.NET 1.1 وعندما تقوم بتعداد المحتويات المخزنة مؤقتًا، لن يتم سرد أية فتحات للنظام بعد الآن.
ربما يكون InProc هو خيار الوصول الأسرع على الإطلاق. لكن ضع في اعتبارك أنه كلما زاد عدد البيانات المخزنة في الجلسة، زاد استهلاك خادم الويب للذاكرة، مما قد يزيد من خطر تدهور الأداء. إذا كنت تخطط لاستخدام أي حل خارج العملية، فيجب عليك دراسة التأثيرات المحتملة للتسلسل وإلغاء التسلسل بعناية. يستخدم الحل خارج العملية خدمة Windows NT (aspnet_state.exe) أو جدول SQL Server لتخزين قيم جلسة العمل. ولذلك، تظل حالة الجلسة خارج العملية المنفذة لـ ASP.NET، ويلزم وجود طبقات إضافية من التعليمات البرمجية لإجراء تسلسل وإلغاء التسلسل بين حالة الجلسة ووسيط التخزين الفعلي. يحدث هذا عندما تتم معالجة الطلب ويجب بعد ذلك تحسينه إلى أعلى درجة.
نظرًا لأن بيانات الجلسة تحتاج إلى النسخ من المستودع الخارجي إلى قاموس الجلسة المحلية، فإن الطلب يؤدي إلى تدهور الأداء يتراوح من 15% (خارج العملية) إلى 25% (SQL Server). لاحظ أنه على الرغم من أن هذا مجرد تقدير تقريبي، إلا أنه يجب أن يكون قريبًا من الحد الأدنى من التأثير، وسيكون التأثير الأقصى أعلى بكثير من هذا. في الواقع، هذا التقدير لا يأخذ في الاعتبار بشكل كامل مدى تعقيد الأنواع المحفوظة بالفعل في حالة الجلسة.
في سيناريو التخزين خارج العملية، تظل حالة الجلسة لفترة أطول، مما يجعل التطبيق أكثر قوة لأنه يحمي من فشل خدمات معلومات الإنترنت Microsoft® (IIS) وASP.NET. من خلال فصل حالة الجلسة عن التطبيقات، يمكنك أيضًا توسيع التطبيقات الموجودة بسهولة أكبر إلى معماريات Web Farm وWeb Garden. بالإضافة إلى ذلك، يتم تخزين حالة الجلسة في عملية خارجية، مما يؤدي بشكل أساسي إلى التخلص من مخاطر فقدان البيانات بشكل دوري بسبب حلقات العملية.
فيما يلي كيفية استخدام خدمات Windows NT. كما هو مذكور أعلاه، فإن خدمة NT هي عملية تسمى aspnet_state.exe، وتقع عادةً في المجلد C:WINNTMicrosoft.NETFrameworkv1.1.4322.
يعتمد الدليل الفعلي على إصدار Microsoft® .NET Framework الذي تقوم بتشغيله بالفعل. قبل استخدام خادم الحالة، يجب عليك التأكد من أن الخدمة جاهزة وتعمل على الكمبيوتر المحلي أو البعيد الذي يتم استخدامه كجهاز تخزين الجلسة. تعد خدمة الحالة جزءًا من ASP.NET ويتم تثبيتها باستخدامه، لذا لا تحتاج إلى تشغيل برنامج تثبيت إضافي. افتراضيًا، خدمة الحالة ليست قيد التشغيل ويجب تشغيلها يدويًا. سيحاول تطبيق ASP.NET إنشاء اتصال بخادم الحالة فورًا بعد تحميله. ولذلك، يجب أن تكون الخدمة جاهزة وقيد التشغيل، وإلا سيتم طرح استثناء HTTP. الصورة التالية توضح مربع حوار الخصائص الخاص بالخدمة.
الشكل 2: مربع حوار خصائص خادم حالة ASP.NET
تحتاج تطبيقات ASP.NET إلى تحديد عنوان TCP/IP للكمبيوتر الذي توجد به خدمة حالة الجلسة. يجب إدخال الإعدادات التالية في ملف web.config الخاص بالتطبيق.
<التكوين>؛
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
;
تحتوي سمة StateConnectionString على عنوان IP الخاص بالكمبيوتر والمنفذ المستخدم لتبادل البيانات. عنوان الكمبيوتر الافتراضي هو 127.0.0.1 (مضيف محلي) والمنفذ الافتراضي هو 42424. يمكنك أيضًا الإشارة إلى الكمبيوتر بالاسم. يعد استخدام جهاز كمبيوتر محلي أو بعيد أمرًا شفافًا تمامًا بالنسبة للتعليمات البرمجية. لاحظ أنه لا يمكن استخدام أحرف غير ASCII في الاسم، كما أن رقم المنفذ إلزامي.
إذا كنت تستخدم وحدة تخزين جلسة العمل خارج العملية، فستظل حالة الجلسة موجودة وستكون متاحة للاستخدام المستقبلي بغض النظر عما يحدث لعملية ASP.NET العاملة. في حالة انقطاع الخدمة، سيتم الاحتفاظ بالبيانات واسترجاعها تلقائيًا عند استعادة الخدمة. ومع ذلك، إذا توقفت خدمة موفر الحالة أو فشلت، فسيتم فقدان البيانات. إذا كنت تريد أن يكون تطبيقك قويًا، فاستخدم وضع SQLServer بدلاً من وضع StateServer.
<التكوين>؛
sqlConnectionString="server=127.0.0.1;uid=<معرف المستخدم>;;pwd=<كلمة المرور>;;"
</system.web>;
؛
يمكنك تحديد سلسلة الاتصال من خلال سمة sqlConnectionString. لاحظ أن سلسلة السمة يجب أن تحتوي على معرف المستخدم وكلمة المرور واسم الخادم. لا يمكن أن تحتوي على علامات مثل قاعدة البيانات والكتالوج الأولي لأن هذه المعلومات افتراضية باسم ثابت. يمكن استبدال معرفات المستخدم وكلمات المرور بإعدادات الأمان المتكاملة.
كيفية إنشاء قاعدة بيانات؟ يوفر ASP.NET زوجين من البرامج النصية لتكوين بيئة قاعدة البيانات. تمت تسمية الزوج الأول من البرامج النصية باسم InstallSqlState.sql وUninstallSqlState.sql، وهما موجودان في نفس المجلد مثل خدمة Session State NT. يقومون بإنشاء قاعدة بيانات باسم ASPState والعديد من الإجراءات المخزنة. ومع ذلك، يتم تخزين البيانات في قاعدة بيانات TempDB لمنطقة التخزين المؤقتة لـ SQL Server. وهذا يعني أنه في حالة إعادة تشغيل جهاز الكمبيوتر SQL Server، سيتم فقدان بيانات الجلسة.
للتغلب على هذا القيد، استخدم زوجًا ثانيًا من البرامج النصية. تمت تسمية الزوج الثاني من البرامج النصية باسم InstallPersistSqlState.sql وUninstallPersistSqlState.sql. في هذه الحالة، يتم إنشاء قاعدة بيانات ASPState، ولكن يتم إنشاء الجداول في نفس قاعدة البيانات وتكون ثابتة أيضًا. عند تثبيت دعم SQL Server لجلسات العمل، يتم أيضًا إنشاء مهمة لحذف جلسات العمل منتهية الصلاحية في قاعدة بيانات حالة جلسة العمل. تُسمى المهمة ASPState_Job_DeleteExpiredSessions وهي قيد التشغيل دائمًا. يرجى ملاحظة أنه لكي تعمل هذه المهمة بشكل صحيح، يجب تشغيل خدمة SQLServerAgent.
بغض النظر عن الوضع الذي تختاره، فإن طريقة ترميز عمليات حالة الجلسة لا تتغير. يمكنك دائمًا العمل على خاصية الجلسة وقراءة القيم وكتابتها كالمعتاد. يتم التعامل مع جميع الاختلافات في السلوك على مستوى أدنى من التجريد. ربما يكون تسلسل الحالة هو الفرق الأكثر أهمية بين أوضاع الجلسة.
تسلسل الحالة وإلغاء التسلسل
عند استخدام وضع التشغيل، يتم تخزين الكائنات في حالة الجلسة كمثيلات نشطة للفئات الخاصة بها. إذا لم يحدث أي تسلسل أو إلغاء تسلسل حقيقي، فهذا يعني أنه يمكنك بالفعل تخزين أي كائن تقوم بإنشائه في الجلسة (بما في ذلك الكائنات التي لا يمكن إجراء تسلسل لها وكائنات COM)، ولن يكون الوصول إليها مكلفًا للغاية. إذا اخترت مزود حالة خارج العملية، فهذه قصة أخرى.
في البنية خارج العملية، يتم نسخ قيم الجلسة من وسائط التخزين المحلية (قاعدة بيانات AppDomain الخارجية) إلى ذاكرة AppDomain التي تعالج الطلب. مطلوب طبقة تسلسل/إلغاء تسلسل لإنجاز هذه المهمة وتمثل إحدى التكاليف الرئيسية لموفري الحالة خارج العملية. التأثير الرئيسي لهذا الموقف على التعليمات البرمجية الخاصة بك هو أنه يمكن تخزين الكائنات القابلة للتسلسل فقط في قاموس الجلسة.
يستخدم ASP.NET طريقتين لإجراء تسلسل للبيانات وإلغاء تسلسلها، اعتمادًا على نوع البيانات المعنية. بالنسبة للأنواع الأساسية، يستخدم ASP.NET مُسلسلًا داخليًا محسّنًا؛ أما بالنسبة للأنواع الأخرى، بما في ذلك الكائنات والفئات المعرفة من قبل المستخدم، يستخدم ASP.NET المنسق الثنائي .NET. تتضمن الأنواع الأساسية السلاسل وأوقات التاريخ والقيم المنطقية والبايتات والأحرف وجميع الأنواع الرقمية. بالنسبة لهذه الأنواع، يعد استخدام برنامج تسلسلي مخصص أسرع من استخدام المنسق الثنائي الافتراضي .NET.
لا يتم إصدار أو توثيق المُسلسِل المُحسّن علنًا. إنه مجرد قارئ/كاتب ثنائي ويستخدم بنية تخزين بسيطة ولكنها فعالة. يستخدم المُسلسل فئة BinaryWriter لكتابة تمثيل بايت للنوع، ثم يكتب تمثيل بايت للقيمة المقابلة لهذا النوع. عند قراءة وحدات البايت المتسلسلة، تقوم الفئة أولاً باستخراج بايت، وتكتشف نوع البيانات المراد قراءتها، ثم تستدعي أسلوب ReadXxx الخاص بالنوع في فئة BinaryReader.
لاحظ أن حجم الأنواع المنطقية والرقمية معروف جيدًا، ولكن ليس بالنسبة للسلاسل. في تدفق البيانات الأساسي، تكون السلسلة دائمًا مسبوقة بطول ثابت (رمز صحيح مكون من 7 بتات مكتوب في المرة الواحدة)، ويستخدم القارئ هذه الحقيقة لتحديد الحجم الصحيح للسلسلة. يتم حفظ قيمة التاريخ عن طريق كتابة العدد الإجمالي للرموز المميزة التي تشكل التاريخ فقط. ولذلك، لإجراء تسلسل للجلسة، يجب أن يكون التاريخ من النوع Int64.
يمكنك استخدام فئة BinaryFormatter لإجراء عمليات التسلسل على كائنات أكثر تعقيدًا (بالإضافة إلى كائنات مخصصة) طالما تم وضع علامة على الفئة التي تحتوي عليها على أنها قابلة للتسلسل. يتم تحديد جميع الأنواع غير الأساسية بواسطة نفس معرف النوع ويتم تخزينها في نفس دفق البيانات مثل الأنواع الأساسية. بشكل عام، يمكن أن تؤدي عمليات التسلسل إلى انخفاض الأداء بنسبة 15% إلى 25%. ومع ذلك، لاحظ أن هذا تقدير تقريبي يعتمد على افتراض استخدام الأنواع الأساسية. كلما كانت الأنواع المستخدمة أكثر تعقيدًا، زادت النفقات العامة.
من الصعب تنفيذ تخزين بيانات الجلسة بكفاءة دون الاستخدام المكثف للأنواع البدائية. لذلك، من الناحية النظرية على الأقل، يعد استخدام ثلاث فتحات جلسة لحفظ ثلاث خصائص سلسلة مختلفة لكائن ما أفضل من إجراء تسلسل للكائن بأكمله. ولكن ماذا لو كان الكائن الذي تريد إجراء تسلسل له يحتوي على 100 خاصية؟ هل تريد استخدام 100 فتحة أم فتحة واحدة فقط؟ في كثير من الحالات، يكون الأسلوب الأفضل هو تحويل نوع معقد إلى عدة أنواع أبسط. يعتمد هذا الأسلوب على محولات النوع. "محول النوع" هو مُسلسل خفيف الوزن يُرجع الخصائص الرئيسية للنوع كمجموعة من السلاسل. محولات النوع هي فئات خارجية مرتبطة بفئة أساسية باستخدام السمات. الأمر متروك لكاتب النوع لتحديد الخصائص التي سيتم حفظها وكيفية حفظها. تعد محولات النوع مفيدة أيضًا لتخزين ViewState وتمثل طريقة أكثر كفاءة لتخزين الجلسة من المنسقات الثنائية.
دورة حياة الجلسة
إحدى النقاط المهمة حول إدارة جلسة ASP.NET هي أن دورة حياة كائن حالة الجلسة تبدأ فقط عند إضافة العنصر الأول إلى قاموس الذاكرة. تعتبر جلسة ASP.NET قد بدأت فقط بعد تنفيذ مقتطف التعليمات البرمجية التالي.
Session["MySlot"] = "Some data";
يحتوي قاموس الجلسة عادةً على نوع الكائن لقراءة البيانات بشكل عكسي، يجب تحويل القيمة التي تم إرجاعها إلى نوع أكثر تحديدًا.
string data = (string) Session["MySlot"]؛
عندما تحفظ الصفحة البيانات في الجلسة، سيتم تحميل القيمة في فئة القاموس المصممة خصيصًا والموجودة في فئة HttpSessionState. يتم تحميل محتويات القاموس إلى موفر الحالة عند اكتمال الطلب الذي تتم معالجته حاليًا. إذا كانت حالة الجلسة فارغة لأنه لم يتم وضع البيانات في القاموس برمجيًا، فلن يتم إجراء تسلسل للبيانات إلى وسيط التخزين، والأهم من ذلك، لن يتم تقديمها في ASP.NET Cache أو SQL Server أو NT State Services Create فتحة لتتبع الجلسة الحالية. وذلك لأسباب تتعلق بالأداء، ولكن له تأثير مهم على كيفية التعامل مع معرفات الجلسة: سيتم إنشاء معرف جلسة جديد لكل طلب حتى يتم تخزين بعض البيانات في قاموس الجلسة.
عندما يكون من الضروري ربط حالة الجلسة بطلب قيد المعالجة، تقوم وحدة HTTP باسترداد معرف الجلسة (إذا لم يكن الطلب البادئ) وتبحث عنه في موفر الحالة الذي تم تكوينه. إذا لم يتم إرجاع أي بيانات، تقوم وحدة HTTP بإنشاء معرف جلسة جديد للطلب. يمكن اختبار ذلك بسهولة من خلال الصفحة التالية:
<%@ Page Language="C#" Trace="true" %>;
</html>;
<الجسم>؛