بعد قراءة المقالة التالية، وجدت أن اختبار المؤلف مفيد حقًا للأصدقاء الذين يستخدمون ASP، ويجب أن يكون مشابهًا ليس فقط لـ ASP ولكن للغات الأخرى. يعد إنشاء محتوى ديناميكي على الخادم أحد الأسباب الرئيسية لاستخدام ASP، لذا كان أول مشروع اختبار اخترناه هو تحديد أفضل طريقة لإرسال المحتوى الديناميكي إلى تدفق الاستجابة. هناك خياران أساسيان (وبعض الأشكال المختلفة منهما): استخدام علامات ASP المضمنة واستخدام عبارة Response.Write.
لاختبار هذه الأساليب المختلفة، قمنا بإنشاء صفحة ASP بسيطة تحدد بعض المتغيرات ثم قمنا بإدراجها في جدول. على الرغم من أن هذه الصفحة بسيطة وليس لها أي فائدة عملية، إلا أنها كافية للسماح لنا بعزل واختبار القضايا الفردية.
2.1 استخدام علامات ASP المضمنة
الاختبار الأول هو استخدام علامة ASP المضمنة <%= x %>، حيث x متغير. هذه هي الطريقة الأكثر ملاءمة للاستخدام، وتسهل قراءة جزء HTML من الصفحة وصيانته.
انسخ رمز الكود كما يلي:
<% خيار صريح
الاسم الأول خافت
DimLastName
خافت الأوسط الأولي
عنوان خافت
مدينة خافتة
الدولة القاتمة
رقم الهاتف الخافت
رقم الفاكس خافت
خافت البريد الإلكتروني
DimBirthDate
الاسم الأول = جون
MiddleInitial = س
اسم العائلة = عام
العنوان = 100 الشارع الرئيسي
المدينة = نيويورك
الولاية = نيويورك
رقم الهاتف = 1-212-555-1234
رقم الفاكس = 1-212-555-1234
البريد الإلكتروني = [email protected]
تاريخ الميلاد = 1/1/1950
%>
<أتش تي أم أل>
<الرأس>
<TITLE>اختبار الاستجابة</TITLE>
</الرأس>
<الجسم>
<H1>اختبار الاستجابة</H1>
<جدول>
<tr><td><b>الاسم الأول:</b></td><td><%= الاسم الأول %></td></tr>
<tr><td><b>الأحرف الأولى المتوسطة:</b></td><td><%= الأحرف الأولى المتوسطة %></td></tr>
<tr><td><b>الاسم الأخير:</b></td><td><%= الاسم الأخير %></td></tr>
<tr><td><b>العنوان:</b></td><td><%= العنوان %></td></tr>
<tr><td><b>المدينة:</b></td><td><%= المدينة %></td></tr>
<tr><td><b>الحالة:</b></td><td><%= الحالة %></td></tr>
<tr><td><b>رقم الهاتف:</b></td><td><%= رقم الهاتف %></td></tr>
<tr><td><b>رقم الفاكس:</b></td><td><%= رقم الفاكس %></td></tr>
<tr><td><b>البريد الإلكتروني:</b></td><td><%= البريد الإلكتروني %></td></tr>
<tr><td><b>تاريخ الميلاد:</b></td><td><%= تاريخ الميلاد %></td></tr>
</الجدول>
</الجسم>
</HTML>
الكود الكامل لـ /app1/response1.asp
أفضل سجل = 8.28 مللي ثانية/صفحة
2.2 استخدم Response.Write لإخراج كل سطر من تعليمات HTML البرمجية
هناك الكثير من الأدبيات الجيدة التي تنص على أنه يجب تجنب أسلوب العلامات المضمنة السابق لأنه يؤدي إلى عملية تسمى تبديل السياق. تحدث هذه العملية عندما يتغير نوع التعليمات البرمجية التي تتم معالجتها بواسطة خادم الويب (من إرسال HTML خالص إلى معالجة البرنامج النصي، أو العكس)، ويستغرق هذا التبديل قدرًا معينًا من الوقت. بعد أن تعلم العديد من المبرمجين ذلك، كان رد فعلهم الأول هو استخدام وظيفة Response.Write لإخراج كل سطر من تعليمات HTML البرمجية:
انسخ رمز الكود كما يلي:
...
الاستجابة.الكتابة(<html>)
الاستجابة.الكتابة(<الرأس>)
Response.Write( <title>اختبار الاستجابة</title>)
الاستجابة.الكتابة(</head>)
الاستجابة.الكتابة(<body>)
الاستجابة.الكتابة(<h1>اختبار الاستجابة</h1>)
الاستجابة.الكتابة(<الجدول>)
الاستجابة.اكتب(<tr><td><b>الاسم الأول:</b></td><td> والاسم الأول & </td></tr>)
Response.Write(<tr><td><b>الأحرف الأولية الوسطى:</b></td><td> والأحرف الأولية الوسطى & </td></tr>)
...
جزء /app1/response2.asp
أفضل سجل = 8.28 مللي ثانية/صفحة
زمن الاستجابة = 8.08 مللي ثانية/صفحة
الفرق = -0.20 مللي ثانية (تخفيض بنسبة 2.4%)
كان التحسن الذي شهدناه في الأداء مقارنة بإصدار العلامات المضمنة صغيرًا جدًا لدرجة أنه كان مفاجئًا بكل بساطة. قد يكون هذا بسبب وجود العديد من استدعاءات الوظائف في الصفحة. ومع ذلك، فإن هذه الطريقة لها عيب أكبر، نظرًا لأن كود HTML مضمن في الوظيفة، يصبح رمز البرنامج النصي طويلًا جدًا وغير مريح للقراءة والصيانة.
2.3 استخدام وظائف المجمع
لا يقوم Response.Write بإضافة CRLF (سطر الإرجاع - تغذية السطر، إرجاع السطر - تغذية السطر) في نهاية سطر النص، وهو الجانب الأكثر إحباطًا لاستخدام الطريقة المذكورة أعلاه. على الرغم من أن كود HTML تم تنسيقه بشكل جيد من جانب الخادم، إلا أن ما تراه في المتصفح لا يزال مجرد سطر طويل من التعليمات البرمجية. لكن هذه المشكلة لم تكن خيبة الأمل الوحيدة، وسرعان ما اكتشف الأشخاص عدم وجود وظيفة Response.WriteLn التي يمكنها إضافة CRLF تلقائيًا. رد الفعل الطبيعي هو إنشاء وظيفة مجمعة للاستجابة. اكتب وأضف CRLF بعد كل سطر:
...
writeCR(<tr><td><b>الاسم الأول:</b></td><td> والاسم الأول & </td></tr>)
...
كتابة فرعيةCR(str)
الاستجابة.الكتابة (str & vbCRLF)
نهاية الفرعية
جزء /app1/response4.asp
أفضل سجل = 8.08 مللي ثانية/صفحة
زمن الاستجابة = 10.11 مللي ثانية/صفحة
الفرق = +2.03 مللي ثانية (زيادة بنسبة 25.1%)
والنتيجة هي انخفاض كبير في الأداء. بالطبع، يرجع ذلك أساسًا إلى أن هذه الطريقة تضاعف عدد استدعاءات الوظائف، وتأثيرها على الأداء واضح جدًا. يجب تجنب هذا الاستخدام بأي ثمن، حيث ينتج عن CRLF وحدتي بايت إضافيتين في نهاية كل سطر، وهاتان البايتتان غير مفيدتين للمتصفح لعرض الصفحة. في معظم الحالات، يسهل التنسيق الجميل لرمز HTML الموجود على جانب المتصفح على منافسيك قراءة تصميم الصفحة وفهمه.
2.4 دمج الاستجابة المتعددة.الكتابة
بتجاهل الاختبار الأخير حول تغليف الوظائف، ستكون الخطوة المنطقية التالية هي دمج جميع السلاسل من عبارات Response.Write المنفصلة في عبارة واحدة، وبالتالي تقليل عدد استدعاءات الوظائف وتحسين كفاءة التعليمات البرمجية.
انسخ رمز الكود كما يلي:
الاستجابة.الكتابة(<html> & _
<الرأس> & _
<title>اختبار الاستجابة</title> & _
</الرأس> & _
<الجسم> & _
<h1>اختبار الاستجابة</h1> & _
<الجدول> & _
<tr><td><b>الاسم الأول:</b></td><td> & الاسم الأول & </td></tr> & _
...
<tr><td><b>تاريخ الميلاد:</b></td><td> & تاريخ الميلاد & </td></tr> & _
</الجدول> & _
</body> & _
</html>)
جزء /app1/response3.asp
أفضل سجل = 8.08 مللي ثانية/صفحة
زمن الاستجابة = 7.05 مللي ثانية/صفحة
الفرق = -1.03 مللي ثانية (تخفيض بنسبة 12.7%)
وهذا هو أفضل أسلوب على الإطلاق.
2.5 اجمع بين عدة ردود. اكتب وأضف CRLF في نهاية كل سطر
يشعر بعض الأشخاص أيضًا بالقلق الشديد بشأن ما إذا كانت تعليمات HTML البرمجية الخاصة بهم تبدو جميلة على جانب المتصفح، لذلك نضيف حرف إرجاع في نهاية كل سطر من تعليمات HTML البرمجية، باستخدام ثابت vbCRLF، أما رموز الاختبار الأخرى فهي نفس المثال أعلاه .
...
Response.Write(<html> & vbCRLF & _
<head> & vbCRLF & _
<title>اختبار الاستجابة</title> & vbCRLF & _
</head> & vbCRLF & _
...
جزء /app1/response5.asp
أفضل سجل = 7.05 مللي ثانية/صفحة
زمن الاستجابة = 7.63 مللي ثانية/صفحة
الفرق = +0.58 مللي ثانية (زيادة بنسبة 8.5%)
والنتيجة هي انخفاض طفيف في الأداء، ربما بسبب إضافة عمليات تسلسل السلسلة وزيادة النص الناتج.
2.6 التعليقات
بناءً على نتائج اختبار مخرجات ASP أعلاه، نصل إلى قواعد التشفير التالية:
تجنب استخدام ASP المضمن أكثر من اللازم.
قم بدمج أكبر عدد ممكن من عبارات Response.Write في عبارة واحدة.
لا تقم مطلقًا بتغليف Response.Write فقط لإضافة CRLF.
إذا كنت تريد تنسيق إخراج HTML، قم بإضافة CRLF مباشرة بعد عبارة Response.Write.
المخطط التفصيلي: ما هي الطريقة الأكثر فعالية لإخراج المحتوى الذي تم إنشاؤه ديناميكيًا بواسطة ASP؟ ما هي أفضل طريقة لاستخراج مجموعة سجلات قاعدة البيانات؟ تختبر هذه المقالة ما يقرب من 20 مشكلة شائعة في تطوير ASP. ويخبرنا الوقت الذي تعرضه أداة الاختبار: هذه المشكلات التي عادة ما يتم اعتبارها أمرا مفروغا منه لا تستحق الاهتمام فحسب، بل تحتوي أيضًا على أسرار غير متوقعة مخبأة بداخلها.
1. الغرض من الاختبار
يتناول الجزء الأول من هذه المقالة بعض المشكلات الأساسية في تطوير ASP ويقدم بعض نتائج اختبار الأداء لمساعدة القراء على فهم تأثير التعليمات البرمجية الموضوعة على الصفحة على الأداء. ADO هي واجهة قاعدة بيانات عالمية سهلة الاستخدام تم تطويرها بواسطة Microsoft، وتبين أن التفاعل مع قاعدة البيانات من خلال ADO هو أحد أهم تطبيقات ASP، وفي الجزء الثاني سندرس هذا الموضوع.
الوظائف التي توفرها ADO واسعة جدًا، لذا فإن الصعوبة الأكبر في إعداد هذه المقالة هي كيفية تحديد نطاق المشكلة. مع الأخذ في الاعتبار أن استخراج كميات كبيرة من البيانات يمكن أن يزيد الحمل على خادم الويب بشكل كبير، فقد قررنا أن الغرض الرئيسي من هذا القسم هو معرفة التكوين الأمثل لتشغيل مجموعات سجلات ADO. ومع ذلك، حتى بعد تضييق نطاق المشكلة، ما زلنا نواجه صعوبات كبيرة، لأن ADO يمكن أن يكون لديه العديد من الطرق المختلفة لإكمال نفس المهمة. على سبيل المثال، يمكن استخراج مجموعات السجلات ليس فقط من خلال فئة مجموعة السجلات، ولكن أيضًا من خلال فئات الاتصال والأوامر؛ حتى بعد الحصول على كائن مجموعة السجلات، هناك العديد من طرق التشغيل التي قد تؤثر بشكل كبير على الأداء. ومع ذلك، كما في الجزء الأول، سنحاول تغطية أوسع نطاق ممكن من القضايا.
وعلى وجه التحديد، فإن الهدف من هذا القسم هو جمع معلومات كافية للإجابة على الأسئلة التالية:
هل يجب الإشارة إلى ADOVBS.inc من خلال التضمين؟
هل يجب علي إنشاء كائن اتصال منفصل عند استخدام مجموعات السجلات؟
ما هي أفضل طريقة لاستخراج مجموعة السجلات؟
lما هو نوع المؤشر وطريقة قفل السجل الأكثر كفاءة؟
هل يجب أن أستخدم مجموعة سجلات محلية؟
ما هي أفضل طريقة لتعيين خصائص مجموعة السجلات؟
ما هي الطريقة الأكثر فعالية للإشارة إلى قيم الحقول في مجموعة السجلات؟
هل هي طريقة جيدة لجمع المخرجات باستخدام سلسلة مؤقتة؟
2. بيئة الاختبار
تم استخدام إجمالي 21 ملف ASP في هذا الاختبار، والتي يمكن تنزيلها من الجزء الخلفي من هذه المقالة. يتم إعداد كل صفحة لتشغيل ثلاثة استعلامات مختلفة، وإرجاع 0 و25 و250 سجلًا على التوالي. سيساعدنا هذا على عزل عملية التهيئة والتشغيل للصفحة نفسها عن الحمل الناتج عن التكرار عبر مجموعة السجلات.
لتسهيل الاختبار، يتم حفظ سلسلة اتصال قاعدة البيانات وسلسلة أوامر SQL كمتغيرات التطبيق في Global.asa. نظرًا لأن قاعدة بيانات الاختبار الخاصة بنا هي SQL Server 7.0، فإن سلسلة الاتصال تحدد OLEDB كموفر الاتصال، وتأتي بيانات الاختبار من قاعدة بيانات Northwind الخاصة بـ SQL Server. يستخرج أمر SQL SELECT 7 حقول محددة من جدول NorthWind Orders.
انسخ رمز الكود كما يلي:
<لغة البرنامج النصي=VBScript RUNAT=الخادم>
التطبيق الفرعي_OnStart
التطبيق (كون) = الموفر=SQLOLEDB;
الخادم = & _
uid=sa;
الأشخاص ذوي الإعاقة =; & _
قاعدة البيانات = الرياح الشمالية
التطبيق (SQL) = SELECTTOP 0OrderID، & _
معرف العميل، & _
معرف الموظف، & _
تاريخ الطلب، & _
التاريخ المطلوب، & _
تاريخ الشحن، & _
الشحن و _
من [الأوامر]
نهاية الفرعية
</النص>
"SQL البديل - 25 سجلا."
التطبيق (SQL) = SELECTTOP 25OrderID، & _
معرف العميل، & _
معرف الموظف، & _
تاريخ الطلب، & _
التاريخ المطلوب، & _
تاريخ الشحن، & _
الشحن و _
من [الأوامر]
"سجلات SQL-250 البديلة"
التطبيق (SQL) = SELECTTOP 250 معرف الطلب، & _
معرف العميل، & _
معرف الموظف، & _
تاريخ الطلب، & _
التاريخ المطلوب، & _
تاريخ الشحن، & _
الشحن و_
من [الأوامر]
كان تكوين خادم الاختبار كما يلي: Pentium بسرعة 450 ميجاهرتز، وذاكرة الوصول العشوائي (RAM) سعة 512 ميجابايت، وNT Server 4.0 SP5، وMDAC 2.1 (مكون الوصول إلى البيانات)، وMicrosoft Scripting Engine الإصدار 5.0. يعمل SQL Server على جهاز آخر بتكوين مماثل. كما هو الحال في الجزء الأول، ما زلنا نستخدم Microsoft Web Application Stress Tool لتسجيل الوقت من طلب الصفحة الأولى إلى آخر بايت تم استلامه من الخادم (TTLB، Time To Last Byte)، الوقت بالمللي ثانية. استدعى البرنامج النصي للاختبار كل صفحة أكثر من 1300 مرة واستغرق تشغيله حوالي 20 ساعة. الأوقات الموضحة أدناه هي متوسط TTLB للجلسة. تذكر، كما في الجزء الأول، نحن مهتمون فقط بكفاءة الكود، وليس قابلية التوسع أو أداء الخادم.
لاحظ أيضًا أننا قمنا بتمكين التخزين المؤقت للخادم. بالإضافة إلى ذلك، من أجل جعل جميع أسماء الملفات بنفس الطول، تحتوي بعض أسماء الملفات على شرطة سفلية واحدة أو أكثر مضمنة فيها.
3. الاختبار الأول
في الاختبار الأول، قمنا باستخراج مجموعة سجلات تحاكي سيناريو نموذجيًا موجودًا في نماذج Microsoft ASP ADO. في هذا المثال (ADO__01.asp)، نقوم أولاً بفتح اتصال ثم نقوم بإنشاء كائن مجموعة السجلات. بالطبع، تم تحسين البرنامج النصي هنا وفقًا لقواعد الترميز الملخصة في الجزء الأول من هذه المقالة.
انسخ رمز الكود كما يلي:
<% خيار صريح %>
<!-- #Include file=ADOVBS.INC -->
<%
خافت objConn
خافت objRS
الاستجابة.اكتب(_
<HTML><HEAD> & _
<TITLE>اختبار ADO</TITLE> & _
</الرأس><الجسم> _
)
تعيين objConn = Server.CreateObject(ADODB.Connection)
objConn.Open التطبيق (كون)
تعيين objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
تطبيق objRS.Open (SQL)
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين
الاستجابة.اكتب(_
<حدود الجدول=1> & _
<TR> & _
<TH>معرف الطلب</TH> & _
<TH>معرف العميل</TH> & _
<TH>معرف الموظف</TH> & _
<TH>تاريخ الطلب</TH> & _
<TH>التاريخ المطلوب</TH> & _
<TH>تاريخ الشحن</TH> & _
<TH>الشحن</TH> & _
</TR> _
)
"اكتب البيانات."
افعل بينما لا objRS.EOF
الاستجابة.اكتب(_
<TR> & _
<TD> & objRS(معرف الطلب) & </TD> & _
<TD> & objRS(معرف العميل) & </TD> & _
<TD> & objRS(EmployeeID) & </TD> & _
<TD> & objRS(OrderDate) & </TD> & _
<TD> & objRS(RequiredDate) & </TD> & _
<TD> & objRS(ShippedDate) & </TD> & _
<TD> & objRS(الشحن) & </TD> & _
</TR> _
)
objRS.MoveNext
حلقة
الاستجابة.كتابة(</TABLE>)
نهاية إذا
objRS.Close
objConn.Close
تعيين objRS = لا شيء
تعيين objConn = لا شيء
الاستجابة.كتابة(</BODY></HTML>)
%>
وهنا نتائج الاختبار:
دعونا نلقي نظرة على معنى الأرقام في كل عمود:
0 يُرجع TTLB (بالملي ثانية) المطلوب لصفحة مكونة من 0 سجلات. في جميع الاختبارات، تعتبر هذه القيمة هي الوقت الإضافي لإنشاء الصفحة نفسها (بما في ذلك إنشاء الكائنات)، باستثناء وقت التكرار عبر بيانات مجموعة السجلات.
25 TTLB بالمللي ثانية لجلب وعرض 25 سجلاً
يتم تقسيم TTLB في عمود الوقت الإجمالي/2525 على 25، وهو إجمالي متوسط تكلفة الوقت لكل سجل.
وقت التوزيع/2525 عمود TTLB ناقص 0 عمود TTLB، ثم قسّم على 25. تعكس هذه القيمة الوقت اللازم لعرض سجل واحد أثناء التكرار عبر مجموعة السجلات.
250 يستخرج ويعرض TTLB من 250 سجلاً.
يتم تقسيم TTLB في العمود إجمالي الوقت/250250 على 25. تمثل هذه القيمة إجمالي متوسط تكلفة الوقت لسجل واحد.
وقت العرض/250 يتم طرح TTLB في العمود 250 من TTLB في العمود 0، ثم يتم تقسيمه على 250. تعكس هذه القيمة الوقت اللازم لعرض سجل واحد أثناء التكرار عبر مجموعة السجلات.
سيتم استخدام نتائج الاختبار المذكورة أعلاه للمقارنة مع نتائج الاختبار التالي.
4. هل يجب الإشارة إلى ADOVBS.inc من خلال التضمين؟
يحتوي ADOVBS.inc الذي توفره Microsoft على 270 سطرًا من التعليمات البرمجية التي تحدد معظم ثوابت خاصية ADO. يشير مثالنا إلى ثابتين فقط من ADOVBS.inc. لذلك، في هذا الاختبار (ADO__02.asp) قمنا بحذف مرجع الملف المضمن واستخدمنا القيمة المقابلة مباشرة عند تعيين الخصائص.
objRS.CursorType = 0؟' adOpenForwardOnly
objRS.LockType = 1' adLockReadOnly
يمكنك أن ترى أن الحمل الزائد للصفحة انخفض بنسبة 23%. لا تؤثر هذه القيمة على وقت جلب وعرض السجلات الفردية، حيث أن التغييرات هنا لا تؤثر على عمليات مجموعة السجلات داخل الحلقة. هناك عدة طرق لحل مشكلات مرجع ADOVBS.inc. نوصي باستخدام ملف ADOVBS.inc كمرجع وشرح الإعدادات عبر التعليقات. تذكر، كما هو مذكور في الجزء الأول، الاستخدام المعتدل للتعليقات له تأثير ضئيل على كفاءة التعليمات البرمجية الخاصة بك. هناك طريقة أخرى وهي نسخ الثوابت التي تحتاجها من ملف ADOVBS.inc إلى الصفحة.
توجد أيضًا طريقة جيدة لحل هذه المشكلة، وهي إتاحة كافة ثوابت ADO مباشرةً عن طريق الارتباط بمكتبة أنواع ADO. أضف التعليمة البرمجية التالية إلى ملف Global.asa للوصول مباشرة إلى كافة ثوابت ADO:
<!--نوع بيانات التعريف=typelib
FILE=C:Program FilesCommon FilesSYSTEMADOmsado15.dll
NAME=مكتبة النوع ADODB -->
أو:
<!--نوع بيانات التعريف=typelib
UUID=00000205-0000-0010-8000-00AA006D2EA4
NAME=مكتبة النوع ADODB -->
ولذلك فإن قاعدتنا الأولى هي:
تجنب تضمين ملف ADOVBS.inc والوصول إلى ثوابت ADO واستخدامها من خلال طرق أخرى.
5. هل يجب علي إنشاء كائن اتصال منفصل عند استخدام مجموعة السجلات؟
للإجابة على هذا السؤال بشكل صحيح، يجب علينا تحليل الاختبار في ظل شرطين مختلفين: أولاً، تحتوي الصفحة على معاملة قاعدة بيانات واحدة فقط؛ ثانيًا، تحتوي الصفحة على معاملات قاعدة بيانات متعددة؛
في المثال السابق، قمنا بإنشاء كائن اتصال منفصل وقمنا بتعيينه إلى خاصية ActiveConnection لمجموعة السجلات. ومع ذلك، كما هو موضح في ADO__03.asp، يمكننا أيضًا تعيين سلسلة الاتصال مباشرةً إلى خاصية ActiveConnection، مما يؤدي إلى التخلص من الخطوة الإضافية المتمثلة في تهيئة كائن الاتصال وتكوينه في البرنامج النصي.
objRS.ActiveConnection = التطبيق(Conn)
على الرغم من أن كائن Recordset لا يزال بحاجة إلى إنشاء اتصال، إلا أن الإنشاء في هذا الوقت يتم تنفيذه في ظل ظروف محسنة للغاية. ونتيجة لذلك، انخفض الحمل الزائد للصفحة بنسبة 23% أخرى مقارنة بالاختبار السابق، وكما هو متوقع، لم يتغير وقت عرض سجل واحد بشكل كبير.
ولذلك فإن قاعدتنا الثانية هي كما يلي:
إذا كنت تستخدم مجموعة سجلات واحدة فقط، فقم بتعيين سلسلة الاتصال مباشرةً إلى خاصية ActiveConnection.
بعد ذلك، نتحقق مما إذا كانت القواعد المذكورة أعلاه لا تزال صالحة عندما تستخدم الصفحة مجموعات سجلات متعددة. لاختبار هذا الوضع، قمنا بإدخال حلقة FOR لتكرار المثال السابق 10 مرات. في هذا الاختبار سوف ننظر في ثلاثة اختلافات:
أولاً، كما هو موضح في ADO__04.asp، يتم إنشاء كائن الاتصال وتدميره في كل حلقة:
انسخ رمز الكود كما يلي:
خافت ط
لأني = 1 إلى 10
تعيين objConn = Server.CreateObject(ADODB.Connection)
objConn.Open التطبيق (كون)
تعيين objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
تطبيق objRS.Open (SQL)
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين
...
"اكتب البيانات."
...
نهاية إذا
objRS.Close
تعيين objRS = لا شيء
objConn.Close
تعيين objConn = لا شيء
التالي
ثانيًا، كما هو موضح في ADO__05.asp، قم بإنشاء كائن اتصال خارج الحلقة وشارك هذا الكائن مع كافة مجموعات السجلات:
انسخ رمز الكود كما يلي:
تعيين objConn = Server.CreateObject(ADODB.Connection)
objConn.Open التطبيق (كون)
خافت ط
لأني = 1 إلى 10
تعيين objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
تطبيق objRS.Open (SQL)
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين
...
"اكتب البيانات."
...
نهاية إذا
objRS.Close
تعيين objRS = لا شيء
التالي
objConn.Close
تعيين objConn = لا شيء
ثالثًا، كما هو موضح في ADO__06.asp، قم بتعيين سلسلة الاتصال لخاصية ActiveConnection في كل حلقة:
انسخ رمز الكود كما يلي:
خافت ط
لأني = 1 إلى 10
تعيين objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = التطبيق(Conn)
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
تطبيق objRS.Open (SQL)
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين
...
"اكتب البيانات."
...
نهاية إذا
objRS.Close
تعيين objRS = لا شيء
التالي
كما يمكننا أن نخمن، فإن إنشاء كائنات الاتصال وتمزيقها داخل الحلقة هي الطريقة الأقل فعالية. ولكن من المثير للدهشة أن تعيين سلسلة الاتصال مباشرةً لخاصية ActiveConnection داخل الحلقة يكون أبطأ قليلاً من مشاركة كائن اتصال واحد.
ومع ذلك فإن القاعدة الثالثة ينبغي أن تكون:
lعند استخدام مجموعات سجلات متعددة في نفس الصفحة، قم بإنشاء كائن اتصال واحد ومشاركته من خلال خاصية ActiveConnection.
6. ما هو نوع المؤشر وطريقة قفل السجل الأكثر كفاءة؟
في جميع الاختبارات التي أجريت حتى الآن، استخدمنا فقط مؤشرات التوجيه فقط للوصول إلى مجموعة السجلات. هناك ثلاثة أنواع من المؤشرات التي يوفرها ADO لمجموعات السجلات: المؤشرات الثابتة القابلة للتمرير، والمؤشرات الديناميكية القابلة للتمرير، ومؤشرات مجموعة المفاتيح. يوفر كل مؤشر وظائف مختلفة، مثل الوصول إلى السجل السابق والسجل التالي، وما إذا كان بإمكانك رؤية تعديلات البيانات بواسطة برامج أخرى، وما إلى ذلك. ومع ذلك، فإن المناقشة التفصيلية لوظائف كل نوع من أنواع المؤشرات تقع خارج نطاق هذه المقالة. ويمثل الجدول التالي تحليلًا مقارنًا لأنواع المؤشرات المختلفة.
تتطلب كافة أنواع المؤشرات الأخرى حملًا إضافيًا مقارنةً بمؤشرات التوجيه فقط، وتكون هذه المؤشرات أبطأ بشكل عام داخل الحلقات. لذلك، نود أن نشارككم التحذير التالي: لا تفكر أبدًا بهذه الطريقة - حسنًا، أحيانًا سأستخدم المؤشرات الديناميكية، لذلك سأستخدم هذا المؤشر دائمًا.
ينطبق نفس الشعور على اختيار طريقة قفل السجل. استخدم الاختبار السابق طريقة القفل للقراءة فقط، ولكن هناك ثلاث طرق أخرى: المعالجة الدفعية المحافظة والمفتوحة والمفتوحة. مثل أنواع المؤشرات، توفر طرق القفل هذه وظائف مختلفة وتحكمًا في العمل مع بيانات مجموعة السجلات.
نصل إلى القواعد التالية:
استخدم أبسط نوع للمؤشر وطريقة قفل السجل المناسبة للمهمة.
7. ما هي الطريقة الأفضل لاستخدامها لاستخراج مجموعة السجلات؟
لقد قمنا حتى الآن باستخراج مجموعات السجلات عن طريق إنشاء كائنات مجموعة السجلات، لكن ADO يوفر أيضًا طرقًا غير مباشرة لاستخراج مجموعة السجلات. يقوم الاختبار التالي بمقارنة ADO__03.asp وإنشاء مجموعة سجلات مباشرة من كائن الاتصال (CONN_01.asp):
انسخ رمز الكود كما يلي:
تعيين objConn = Server.CreateObject(ADODB.Connection)
objConn.Open التطبيق (كون)
تعيين objRS = objConn.Execute(Application(SQL))
يمكنك أن ترى أن حجم الصفحة قد زاد قليلاً ولم يتغير وقت عرض سجل واحد.
دعونا نلقي نظرة على إنشاء كائن مجموعة سجلات (CMD__02.asp) مباشرةً من كائن الأوامر:
انسخ رمز الكود كما يلي:
تعيين objCmd = Server.CreateObject(ADODB.Command)
objCmd.ActiveConnection = التطبيق(Conn)
objCmd.CommandText = التطبيق (SQL)
تعيين objRS = objCmd.Execute
وبالمثل، يزيد مقدار الصفحة قليلاً دون تغيير جوهري في وقت العرض لسجل واحد. الفرق في الأداء بين الطريقتين الأخيرتين صغير، ولكن لدينا مسألة مهمة يجب أخذها في الاعتبار.
عند إنشاء مجموعة سجلات من خلال فئة Recordset، يمكننا التحكم في معالجة مجموعة السجلات بأكبر قدر من المرونة. نظرًا لأن الطريقتين الأخيرتين تفشلان في تحقيق أداء ساحق، فإننا نعتبر بشكل أساسي نوع المؤشر وطريقة قفل السجل التي يتم إرجاعها افتراضيًا، وفي بعض المناسبات، لا تكون القيمة الافتراضية بالضرورة هي الأكثر مثالية.
لذلك، ما لم تكن هناك أسباب خاصة للاختيار بين الطريقتين الأخيرتين، فإننا نوصي بمراعاة القواعد التالية:
l قم بإنشاء مثيل لمجموعة السجلات من خلال فئة ADODB.Recordset للحصول على أفضل أداء ومرونة.
8. هل يجب علي استخدام مجموعة سجلات محلية؟
يسمح ADO باستخدام مجموعات السجلات المحلية (العميل) في هذا الوقت، وسيقوم الاستعلام باستخراج كافة البيانات الموجودة في مجموعة السجلات، بعد اكتمال الاستعلام، يمكن إغلاق الاتصال على الفور، ويمكن استخدام المؤشرات المحلية للوصول إلى البيانات المستقبل، مما يجلب الراحة لتحرير الاتصال. يعد استخدام مجموعات السجلات المحلية أمرًا مهمًا للوصول إلى خدمات البيانات عن بعد التي تتطلب استخدام البيانات دون الاتصال بالإنترنت، ولكن هل سيكون ذلك مفيدًا أيضًا للتطبيقات العادية؟
بعد ذلك نضيف سمة CursorLocation ونغلق الاتصال (CLIENT1.asp) بعد فتح مجموعة السجلات:
انسخ رمز الكود كما يلي:
تعيين objRS = Server.CreateObject(ADODB.Recordset)
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = التطبيق(Conn)
objRS.LockType = 1؟'
تطبيق objRS.Open (SQL)
objRS.ActiveConnection = لا شيء
من الناحية النظرية، قد يفيد هذا الأسلوب الكفاءة لسببين: أولاً، يتجنب طلب البيانات بشكل متكرر من خلال الاتصال عند التنقل بين السجلات؛ ثانيًا، فإنه يخفف متطلبات الموارد. ومع ذلك، يبدو من الجدول أعلاه أن استخدام مجموعة السجلات المحلية لن يساعد بشكل واضح على تحسين الكفاءة. قد يكون هذا بسبب أنه عند استخدام مجموعة سجلات محلية، يصبح المؤشر دائمًا نوعًا ثابتًا بغض النظر عن إعدادات البرنامج.
القاعدة 6 هي كما يلي:
يجب تجنب ذلك ما لم تكن ترجمة مجموعة السجلات مطلوبة بالفعل.
10. ما هي الطريقة الأكثر فعالية للاستخدام للإشارة إلى قيم الحقول في مجموعة السجلات؟
10.1 الاختبار
لقد قمنا حتى الآن بالإشارة إلى قيم الحقول في مجموعة السجلات بالاسم. نظرًا لأن هذه الطريقة تتطلب العثور على الحقل المقابل في كل مرة، فهي ليست فعالة جدًا. لتوضيح ذلك، في الاختبار التالي، نقوم بالإشارة إلى قيمة الحقل حسب فهرسه في المجموعة (ADO__08.asp):
انسخ رمز الكود كما يلي:
"اكتب البيانات."
افعل بينما لا objRS.EOF
الاستجابة.اكتب(_
<TR> & _
<TD> & objRS(0) & </TD> & _
<TD> & objRS(1) & </TD> & _
<TD> & objRS(2) & </TD> & _
<TD> & objRS(3) & </TD> & _
<TD> & objRS(4) & </TD> & _
<TD> & objRS(5) & </TD> & _
<TD> & objRS(6) & </TD> & _
</TR> _
)
objRS.MoveNext
حلقة
كما هو متوقع، هناك أيضًا تغيير بسيط في حجم الصفحة (ربما بسبب انخفاض طفيف في التعليمات البرمجية). ومع ذلك، فإن التحسن في وقت العرض باستخدام هذا الأسلوب ملحوظ تمامًا.
في الاختبار التالي، سنقوم بربط كافة الحقول بالمتغيرات بشكل فردي (ADO__09.asp):
انسخ رمز الكود كما يلي:
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين
...
خافت fld0
خافت fld1
خافت fld2
خافت fld3
خافت fld4
خافت fld5
خافت fld6
تعيين fld0 = objRS(0)
تعيين fld1 = objRS(1)
تعيين fld2 = objRS(2)
تعيين fld3 = objRS(3)
تعيين fld4 = objRS(4)
اضبط fld5 = objRS(5)
تعيين fld6 = objRS(6)
"اكتب البيانات."
افعل بينما لا objRS.EOF
الاستجابة.اكتب(_
<TR> & _
<TD> & fld0 & </TD> & _
<TD> & fld1 & </TD> & _
<TD> & fld2 & </TD> & _
<TD> & fld3 & </TD> & _
<TD> & fld4 & </TD> & _
<TD> & fld5 & </TD> & _
<TD> & fld6 & </TD> & _
</TR> _
)
objRS.MoveNext
حلقة
تعيين fld0 = لا شيء
تعيين fld1 = لا شيء
تعيين fld2 = لا شيء
تعيين fld3 = لا شيء
تعيين fld4 = لا شيء
تعيين fld5 = لا شيء
تعيين fld6 = لا شيء
الاستجابة.كتابة(</TABLE>)
نهاية إذا
وهذا هو أفضل سجل حتى الآن. يرجى ملاحظة أنه تم تقليل وقت عرض سجل واحد إلى أقل من 0.45 مللي ثانية.
تتطلب جميع البرامج النصية المذكورة أعلاه بعض الفهم لبناء مجموعة سجلات النتائج. على سبيل المثال، نستخدم أسماء الحقول مباشرة في رؤوس الأعمدة للإشارة إلى كل قيمة حقل على حدة. في الاختبار التالي، لا يتم الحصول على بيانات الحقل فقط عن طريق اجتياز مجموعة الحقول، ولكن يتم أيضًا الحصول على عناوين الحقول بنفس الطريقة، وهذا حل أكثر ديناميكية (ADO__10.asp).
انسخ رمز الكود كما يلي:
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
'اكتب العناوين Response.Write(<TABLE BORDER=1><TR>)
لكل objFld في objRS.Fields
Response.Write(<TH> & objFld.name & </TH>)
التالي
الاستجابة.كتابة(</TR>)
"اكتب البيانات."
افعل بينما لا objRS.EOF
الاستجابة.الكتابة(<TR>)
لكل objFld في objRS.Fields
الاستجابة.الكتابة(<TD> & objFld.value & </TD>)؟
التالي
الاستجابة.كتابة(</TR>)
objRS.MoveNext
حلقة
الاستجابة.كتابة(</TABLE>)
نهاية إذا
كما ترون، انخفض أداء التعليمات البرمجية، لكنه لا يزال أسرع من ADO__07.asp.
مثال الاختبار التالي هو حل وسط للطريقتين السابقتين. سنستمر في الحفاظ على الميزة الديناميكية مع تحسين الأداء عن طريق حفظ مراجع الحقول في المصفوفات المخصصة ديناميكيًا:
انسخ رمز الكود كما يلي:
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
آخر
خافت fldCount
fldCount = objRS.Fields.Count
خافت فلوريدا ()
ريديم فلد (فلدكونت)
خافت ط
لأني = 0 إلى fldCount-1
تعيين fld(i) = objRS(i)
التالي
'اكتب العناوين
Response.Write(<TABLE BORDER=1><TR>) لـ i = 0 إلى fldCount-1
الاستجابة.الكتابة(<TH> & fld(i).name & </TH>)
التالي
الاستجابة.كتابة(</TR>)
"اكتب البيانات."
افعل بينما لا objRS.EOF
الاستجابة.الكتابة(<TR>)
لأني = 0 إلى fldCount-1
الاستجابة.الكتابة(<TD> & fld(i) & </TD>)
التالي
الاستجابة.كتابة(</TR>)
objRS.MoveNext
حلقة
لأني = 0 إلى fldCount-1
اضبط fld(i) = لا شيء
التالي
الاستجابة.كتابة(</TABLE>)
نهاية إذا
على الرغم من أنه لا يتفوق على الأفضل السابق، إلا أنه أسرع من الأمثلة القليلة الأولى، ويتمتع بميزة المعالجة الديناميكية لأي مجموعة من السجلات.
بالمقارنة مع رمز الاختبار السابق، تم تغيير رمز الاختبار التالي بشكل أساسي. فهو يستخدم أسلوب GetRows الخاص بكائن Recordset لملء الصفيف للتكرار عبر البيانات، بدلاً من الوصول مباشرةً إلى مجموعة السجلات نفسها. لاحظ أنه تم تعيين مجموعة السجلات على لا شيء مباشرة بعد استدعاء GetRows، مما يعني أنه سيتم تحرير موارد النظام في أسرع وقت ممكن. لاحظ أيضًا أن البعد الأول للصفيف يمثل الحقول وأن البعد الثاني يمثل الصفوف (ADO__12.asp).
انسخ رمز الكود كما يلي:
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
objRS.Close
تعيين objRS = لا شيء
آخر
'اكتب العناوين
...
"مجموعة المصفوفة."
خافت arrRS
arrRS = objRS.GetRows
'إغلاق مجموعة السجلات في وقت مبكر
objRS.Close
تعيين objRS = لا شيء
"اكتب البيانات."
DimnumRows
DimnumFlds
صف خافت
خافت فلوريدا
numFlds = Ubound(arrRS, 1)
numRows = Ubound(arrRS, 2)
للصف = 0 إلى numRows
الاستجابة.الكتابة(<TR>)
بالنسبة لـ fld = 0 إلى numFlds
الاستجابة.الكتابة(<TD> & arrRS(fld,row) & </TD>)
التالي
الاستجابة.كتابة(</TR>)
التالي
الاستجابة.كتابة(</TABLE>)
نهاية إذا
عند استخدام أسلوب GetRows، يتم استخراج مجموعة السجلات بأكملها إلى صفيف. على الرغم من أن مشاكل الموارد قد تحدث عندما تكون مجموعة السجلات كبيرة للغاية، إلا أن الوصول إلى البيانات في حلقة يكون أسرع بالفعل لأنه يتم إلغاء استدعاءات الوظائف مثل MoveNext والتحقق من EOF.
السرعة لها تكلفة، والآن يتم فقدان البيانات التعريفية لمجموعة السجلات. لحل هذه المشكلة، يمكننا استخراج معلومات الرأس من كائن مجموعة السجلات قبل استدعاء GetRows، بالإضافة إلى ذلك، يمكن أيضًا استخراج نوع البيانات والمعلومات الأخرى مسبقًا. لاحظ أيضًا أن ميزة الأداء في الاختبار تحدث فقط عندما تكون مجموعة السجلات أكبر.
في الاختبار الأخير لهذه المجموعة، نستخدم طريقة GetString لمجموعة السجلات. يستخرج الأسلوب GetString مجموعة السجلات بأكملها في سلسلة كبيرة ويسمح لك بتحديد المحدد (ADO__13.asp):
انسخ رمز الكود كما يلي:
إذا objRS.EOF ثم
الاستجابة.الكتابة (لم يتم العثور على سجلات)
objRS.Close
تعيين objRS = لا شيء
آخر
'اكتب العناوين
...
"مجموعة المصفوفة."
جدول خافت
strTable = objRS.GetString (2, , </TD><TD>, </TD></TR><TR><TD>)
'إغلاق مجموعة السجلات في وقت مبكر
objRS.Close
تعيين objRS = لا شيء
Response.Write(strTable & </TD></TR></TABLE>)
نهاية إذا