1. طريقة الخروج
اعتقدت في البداية أن العملية ستخرج فورًا بعد تنفيذ طريقة الخروج، لكنني غيرت رأيي بعد أن قمت بالفعل بعمل مثال لاختبارها. يرجى النظر في هذا
على سبيل المثال، تم تعيين القيمة "C" للعلم أخيرًا.
================================================================================================== =======================================================================================
فار
العلم: سلسلة؛
يبدأ
يحاول
العلم := 'أ'؛
مخرج؛
العلم := 'ب';
أخيراً
العلم := 'ج';
نهاية؛
العلم := 'د';
نهاية؛
================================================================================================== =======================================================================================
التحليل: بغض النظر عن كيفية انتهاء جملة المحاولة، يتم دائمًا تنفيذ الجملة الأخيرة. (شكرًا لمستخدمي الإنترنت ylmg)
2. مشكلة صغيرة يمكن أن تؤدي إلى توقف النظام بأكمله
في تصميم نظام قاعدة البيانات، غالبًا ما تُستخدم عمليات المعاملات لضمان تكامل البيانات، ومع ذلك، يمكن أن يكون للتصميم غير المناسب تأثير كبير نسبيًا. يوضح المثال التالي أنه على الرغم من ضمان تكامل البيانات، فقد يتوقف النظام عن العمل تمامًا:
================================================================================================== =======================================================================================
AdoConnection1.BeginTrans;
يحاول
...
إذا application.MessageBox('هل أنت متأكد من الحذف؟'، 'سؤال'، MB_YESNO+MB_ICONQUESTION)<>IDنعم إذن //(1)
يبدأ
...
نهاية؛
Application.MessageBox("فشلت العملية"، "تحذير"، MB_OK //(2) ؛
AdoConnection1.CommitTrans;
يستثني
Application.MessageBox("فشلت العملية"، "تحذير"، MB_OK //(3) ؛
AdoConnection1.RollbackTrans;
نهاية؛
================================================================================================== =======================================================================================
التحليل: المشاكل الموجودة في الكود أعلاه كلها ناجمة عن Application.MessageBox في (1) و(2) و(3)، ولكن ليس Application.MessageBox نفسه هو الذي يسبب المشكلة، ولكنه يعلق البرنامج ويتطلب المستخدم التدخل، ثم الاستمرار في تنفيذ العمليات اللاحقة؛ إذا ترك المستخدم الكمبيوتر في هذا الوقت، أو لم يؤكد تشغيل مربعات الحوار هذه، فمن الممكن أن يكون النظام بأكمله في حالة انتظار لأن هذه المعاملة لم تنته. .
ولتجنب هذه المشكلة هناك قاعدتان:
(1) بعد بدء المعاملة، يمكن للبرنامج إنهاء المعاملة تلقائيًا دون تدخل المستخدم؛
(2) قم بأقصر عملية في المعاملة.
3. حاول...إلا...الهيكل النهائي
فيما يلي مثال لتوضيح بنية المحاولة، أو مثال لاستخدام عمليات المعاملة:
الكود المعني:
================================================================================================== =======================================================================================
يحاول
...
AdoConnection1.BeginTrans;
...
AdoConnection1.CommitTrans;
يستثني
AdoConnection1.RollbackTrans;
نهاية؛
================================================================================================== =======================================================================================
التحليل: في حالة حدوث استثناء في التعليمات البرمجية بعد محاولة AdoConnection1.BeginTrans، فسوف ينتقل إلى AdoConnection1.RollbackTrans للتنفيذ، ومع ذلك، لم يبدأ AdoConnection1 المعاملة بسبب خطأ، لذلك حدث خطأ أثناء تنفيذ AdoConnection1.RollbackTrans.
الكود الصحيح : ================================================================== ==========================================================================================
AdoConnection1.BeginTrans;
يحاول
...
...
AdoConnection1.CommitTrans;
يستثني
AdoConnection1.RollbackTrans;
نهاية؛
================================================================================================== =======================================================================================
باختصار، يتم استخدام بنية المحاولة لحماية العمليات غير الطبيعية. في حالة حدوث استثناء بين المحاولة...إلا، سيتم تنفيذ العملية بين الاستثناء...النهاية. عند تصميم أمر المحاولة، يجب الانتباه إلى العقلانية من الهندسة المعمارية.
4. الاحتيال على حماية المعاملات الخاصة
عند إنشاء برنامج تطبيقي لقاعدة البيانات، غالبًا ما نحتاج إلى مواجهة المشكلات التالية: الحكم على البيانات الأصلية ثم إجراء التعديلات المقابلة. تبدو هذه المشكلة بسيطة نسبيًا، لكن إذا اعتبرت أن هناك أشخاصًا آخرين على الشبكة يستخدمون نفس النظام، فعليك أن تفكر في إمكانية حدوث تغييرات غير مقصودة. كان زميلي مهملاً، على الرغم من أنه فكر في مشكلة تعدد المستخدمين بعد مطالبتي، إلا أنه ما زال يكتب الكود الإشكالي:
================================================================================================== =======================================================================================
فار
إعلانات درجة الحرارة: TAdoDataSet؛
isOk: منطقي؛
يبدأ
AdsTemp := TAdoDataSet.Create(self);
يحاول
AdsTemp.Connection := AdoConnection1;
adsTemp.CommandText := 'اختر fid، fnumber من tb1 حيث fid=120'؛
AdsTemp.Open;
isOk :=adsTemp.FieldByName('fnumber').AsInteger>100;
أخيراً
AdsTemp.Free;
نهاية؛
إذا لم يكن على ما يرام ثم
مخرج؛
AdoConnection1.BeginTrans;
يحاول
AdoConnection1.Execute('تحديث مجموعة tb1 ffull=ffull + 1 من tb1 حيث fid=120';
...
...
AdoConnection1.CommitTrans;
يستثني
AdoConnection1.RollbackTrans;
نهاية؛
نهاية؛
================================================================================================== =======================================================================================
التحليل: لا أعرف ما إذا كنت قد رأيت المشكلة أم لا، يتم الحكم على البيانات قبل AdoConnection1.BeginTrans، ثم يتم استخدام AdoConnection1.Execute لتغيير البيانات AdoConnection1.BeginTrans, tb1 ربما تكون البيانات قد تغيرت، وحماية المعاملات هذه ليست ذات فائدة.
الطريقة الصحيحة هي أن الحكم والتعديل يجب أن يكونا نفس البيانات. الأمثلة التالية توضح طريقتين (الفرق هو أن الموقع الذي بدأت فيه المعاملة مختلف):
الكود 1 (بعد استخدام حماية المعاملات، يتم الحكم على نفس البيانات وتعديلها):
================================================================================================== =======================================================================================
فار
إعلانات درجة الحرارة: TAdoDataSet؛
isOk: منطقي؛
يبدأ
AdoConnection1.BeginTrans;
يحاول
AdsTemp := TAdoDataSet.Create(self);
يحاول
AdsTemp.Connection := AdoConnection1;
AdsTemp.CommandText := 'اختر fid، fnumber، ffull من tb1 حيث fid=120'؛
AdsTemp.Open;
إذا AdsTemp.FieldByName('fnumber').AsInteger>100 ثم
يبدأ
AdsTemp.Edit;
AdsTemp.FieldByName('ffull').AsInteger :=adsTemp.FieldByName('ffull').AsInteger + 1;
AdsTemp.Post;
نهاية؛
أخيراً
AdsTemp.Free;
نهاية؛
AdoConnection1.CommitTrans;
يستثني
AdoConnection1.RollbackTrans;
نهاية؛
نهاية؛
================================================================================================== =======================================================================================
الرمز 2 (باستخدام التقاط الاستثناء، إذا لم يكن الحكم والتعديل هما نفس البيانات، فسيحدث استثناء أثناء AdsTemp.Post. هذه إحدى ميزات كائن ADODataSet):
================================================================================================== =======================================================================================
فار
إعلانات درجة الحرارة: TAdoDataSet؛
isOk: منطقي؛
يبدأ
AdsTemp := TAdoDataSet.Create(self);
يحاول
AdsTemp.Connection := AdoConnection1;
AdsTemp.CommandText := 'اختر fid، fnumber، ffull من tb1 حيث fid=120'؛
AdsTemp.Open;
إذا AdsTemp.FieldByName('fnumber').AsInteger>100 ثم
يبدأ
AdoConnection1.BeginTrans;
يحاول
AdsTemp.Edit;
AdsTemp.FieldByName('ffull').AsInteger :=adsTemp.FieldByName('ffull').AsInteger + 1;
AdsTemp.Post;
AdoConnection1.CommitTrans;
يستثني
AdoConnection1.RollbackTrans;
نهاية؛
نهاية؛
أخيراً
AdsTemp.Free;
نهاية؛
نهاية؛