سؤال: لقد كتبت فئة تشغيل قاعدة البيانات TDBPerate_DL لتوحيد العمليات في قاعدة البيانات. يتم توفير طرق للإعلان عن بدء المعاملة، وتنفيذ المعاملة، واستعادة المعاملة للفئات الأخرى للاتصال بها. TDBOperate_DL = class PRivate ADOC:TADOConnection; ADOQ:TADOQuery; isDestroyADOC:Boolean; fIsInTrans:Boolean; // سواء كانت المعاملة قد بدأت public isCommit:Boolean; // سواء تم تنفيذ المعاملة، فالافتراضي صحيح، إذا صوت الفصل ضد التقديم، فهو خطأ function IsInTrans:Boolean buildor Create(const newADOC: TADOConnection );overload; create(const ServerName,DataBaseName,UserID,PassWord:String);overload; destructor Destroy;override; CommitTrans; الإجراء RollbackTrans; تنفيذ الإجراء(const sqlString:String); function GetDataset(const sqlString:String):_Recordset; function GetConnection:TADOConnection; // ابدأ المعاملة start self.ADOC.BeginTrans; self.fIsInTrans := true;end;procedure TDBOperate_DL.CommitTrans; // بدء معاملة الالتزام self.ADOC.CommitTrans; self.fIsInTrans := false;end;procedure TDBOperate_DL.RollbackTrans; self.fIsInTrans := false;end;function TDBPerate_DL.IsInTrans: Boolean; // التحقق مما إذا كانت المعاملة قد بدأت تبدأ النتيجة := self.fIsInTrans;end;اكتب فئة TThing لإضافة أو تعديل أو حذف سجلات حول شيء ما إلى قاعدة البيانات، واستدعاء فئة TDBPerate_DL لإكمالها. لتسهيل الاتصال، يتم وضع المعاملات ذات الصلة في فئة TThing، وليست هناك حاجة للنظر في المعاملة عند إجراء مكالمات خارجية. على سبيل المثال: الإجراء Tthing.Drop(const thing:String);var sqlString:String;begin sqlString :=حذوف عبارة SQL; self.DBPerate.BeginTrans;// DBOperate هو متغير خاص من نوع TDBPerate_DL، يتم تمريره عند إنشاء Tthing معلمات مثيل الفئة. حاول self.DBOperate.Execute(sqlString); self.DBOperate.CommitTrans; يتم وضع نفس المعاملة في فئة TPerson. الآن عندما أرغب في حذف سجل شخص ما، أقوم باستدعاء فئة TThing لحذف الأشياء المتعلقة بالشخص. تنشأ مشكلة في المعاملة: لا يمكن تداخل المعاملات. إذا قمت بحذف TThing أولاً، ثم أعدت إعلان المعاملة لحذف TPerson، وإذا ارتكب TPerson خطأ، فكيف يمكنك استرجاع TThing؟ على سبيل المثال: الإجراء Tperson.Drop(const person:String);var sqlString:String; thing:Tthing;begin sqlString := عبارة SQL محذوفة; Tthing.Create(self.DBOperate); // نوع DBOperate_DL يتم تمريرها كمعلمة. Self.DBOperate.BeginTrans; Try Thing.Drop(person); // هناك معاملة بالداخل، راجع الكود أعلاه Self.DBOperate.Execute(sqlString); end;end ;الحل، التقديم على مرحلتين، أولاً بعض المعرفة الأساسية: بغض النظر عن النظام المكون من مستويين أو ثلاثة مستويات، تتم معالجة المعاملات من خلال التقديم على مرحلتين. في المرحلة الأولى، تتم كتابة كل مورد/سجل تم تنفيذه في بيئة المعاملات (TranscationContext)، ثم يستفسر منسق الموارد بشكل تسلسلي عما إذا كان تنفيذ كل معاملة مشاركة ناجحًا، وإذا لم تكن هناك مشاكل، فإنه يدخل المرحلة الثانية يبدأ التنفيذ بإجراء عملياته. إذا كانت هناك مشكلة في تنفيذ واحد، يقوم منسق الموارد بإعلام جميع عمليات التنفيذ الثانوية للتخلي عن الالتزام واستعادة الحالة الأصلية للبيانات. بالإشارة إلى عملية معاملة COM+، إذا كان أحد المكونات يتطلب معاملة، فقد بدأت المعاملة بالفعل عند إنشاء المكون، عند إتلاف المكون، يتم إجراء تصويت المعاملة تراجعت. (إذا كان المكون يدعم التجميع، فستحدث هاتان الحالتان في حدثي تنشيط المكون والسكون). لذلك نحن نحدد فئة على النحو التالي. // فئة السلف من فئة رجال الأعمال، المستخدمة لتوفير دعم المعاملات الموحدة TTS_DL = class public isRootTrans:Boolean; // سواء كانت معاملة جذر isNeedTrans:Boolean; // ما إذا كانت المعاملة مطلوبة public DBOperate:TDBOperate_DL; تشغيل إجراء مثيل قاعدة البيانات SetComplete؛ SetAbort منشئ Create(const newDBOperate:TDBOperate_DL; needTrans:Boolean);// ما إذا كان مدمر دعم المعاملات مطلوبًا تدمير؛ نهاية؛ عند إنشاء هذه الفئة، بالإضافة إلى تمرير مثيل الفئة التي تدير قاعدة البيانات، يتم تمرير علامة للإشارة إلى ما إذا كانت المعاملة مطلوبة، لأنه إذا كانت مجرد عملية قراءة. قاعدة البيانات، ليست هناك حاجة للمعاملة. رمز تنفيذ الفئة كما يلي: المُنشئ TTS_DL.Create(const newDBOperate: TDBOperate_DL; needTrans: Boolean);begin inherited Create; self.DBOperate := newDBOperate; self.isNeedTrans := needTrans; ثم يبدأ .isNeedTrans // إذا كان في معاملة، فهو ليس المعاملة الجذرية، وتبقى قيمة isCommit في سياق المعاملة دون تغيير إذا self.DBOperate.isInTrans ثم self.isRootTrans := false else begin self.DBOperate.BeginTrans; // إذا كانت المعاملة الجذرية، فابدأ المعاملة self.isRootTrans := true self.DBOperate.isCommit := true; تهيئة علامة الالتزام لتنفيذ المعاملة end;end;destructor TTS_DL.Destroy;begin إذا بدأ self.isNeedTrans // إذا كانت معاملة جذرية، فقم بتنفيذ المعاملة أو التراجع عنها وفقًا لنتائج التصويت. إذا كانت self.isRootTrans تبدأ إذا كانت self.DBOperate.isCommit ثم self.DBOperate.CommitTrans else self.DBOperate.RollbackTrans end; end; الإجراء TTS_DL.SetAbort;ابدأ self.DBOperate.isCommit := self.DBOperate.isCommit وfalse; // التصويت على التراجع؛ إجراء TTS_DL.SetComplete؛ ابدأ self.DBOperate.isCommit := self.DBOperate.isCommit وصحيح؛ // التصويت على الالتزام؛ ارجع إلى فئتي الأعمال Tthing وTperson، هذه المرة تم توريث كل شيء من فئة TTS_DL. Tthing = class(TTS_DL); Tperson = class(TTS_DL); يجب أن يكون رمز الحذف لـ Tthing كما يلي: الإجراء Tthing.Drop(const thing:String);var sqlString:String;begin sqlString := Deleted SQL context; .DBOperate.Execute(sqlString); self.DBOperate.SetComplete; DBOperate.SetAbort; //Vote rollback rise; end;end; رمز الحذف الخاص بـ Tperson هو كما يلي: الإجراء Tperson.Drop(const person:String);var sqlString thing:Tthing;begin sqlString := item SQL := Tthing.Create(self.DBOperate,true); //TDBOperate_DL يتم تمرير النوع DBOperate كمعلمة، صحيح يعني أن المعاملة مطلوبة. حاول تجربة Thing.Drop(person); Self.DBOperate.Execute(sqlString); self.DBOperate.SetComplete; // تذكر إصدار end;end; تذكر الاحتفاظ بالمثيل الوحيد لفئة قاعدة بيانات التشغيل TDBOperate_DL المستخدمة في البرنامج، وتذكر إصدار مثيل فئة الأعمال إذا كانت المعاملة مطلوبة، فقم بتحريرها في أقرب وقت ممكن، حسنًا، منتهي. الإصدار الأول ذو مستوى محدود ويحتاج إلى تحسين في التطبيقات العملية، فهو مجرد وسيلة لجذب أفكار جديدة، يرجى من الأبطال ذوي الخبرة المساهمة :).