طريقة مفضلة لكتابة تطبيقات قاعدة بيانات Delphi مع المعاملات ومكونات مدركة للبيانات

StackOverflow https://stackoverflow.com/questions/3833432

سؤال

ما هي الطريقة المفضلة لكتابة تطبيقات قاعدة بيانات Delphi باستخدام المعاملات وأيضًا مكونات مدركة للبيانات؟

لا بد لي من كتابة تطبيق عميل يمكنه الوصول إلى جداول InnoDB ، والقيام ببعض الأشياء الرئيسية من الأشياء داخل المعاملات. بعد إجراء بعض الأبحاث حول المعاملات (من وجهة نظر عامة) ، ثم أقوم بتواضع بأن المكونات غير المدركة للبيانات و SQL المرفق يدويًا ستكون "المباراة المثالية" للمعاملات ؛ لكن مكونات تدرك البيانات لن تكون كذلك. لا يبدو أنها مصنوعة لبعضهم البعض.

لدي حاجة حقيقية لاستخدام المعاملات ، لكن من ناحية أخرى ، لم أستطع فقط إلقاء مكونات مدركة للبيانات لأنها تبسط الأشياء بشكل كبير.

هل يمكن لأحد أن ينيرني؟ لقد كنت غوغل ، لكنني لم أجد أي إجابة مفيدة. ربما لأن لغتي الإنجليزية ليست جيدة بما يكفي لأن كلماتي الرئيسية محدودة.

راجع للشغل ، أنا أستخدم Delphi 7 وتقييم UNIDAC حاليًا كمكتبة الوصول إلى البيانات.

شكرًا لك.

تعديل

مثال لوصف جانب من جوانب سؤالي:

تخيل نموذجًا يحتوي على 2 dbgrids على ذلك. الشبكة الأولى هي MasterGrid وفوق هذه الأزرار: إضافة ، تحرير وحذف. الشبكة الثانية هي تفاصيل. إذا انقر فوق المستخدم إضافة ، فسيذهب مثل هذا:

  • Connection.StartTransaction
  • Master.Append ثم Master.post ثم Master.edit (وبالتالي فإن مجموعة البيانات الرئيسية لديها المفتاح الأساسي التلقائي ، وهو قابل للتحرير الآن)
  • أظهر نموذج التحرير بشكل معدني ، حيث يقوم المستخدم بملء السجلات الرئيسية ، ويضيف أيضًا بعض سجلات التفاصيل باستخدام نموذج آخر.
  • إذا انقر فوق المستخدم موافق ، فسيقوم التطبيق بعمل Master.post و Connection.Commit. إذا انقر فوق المستخدم إلغاء ، فسيقوم التطبيق بالاتصال. rollback.

أعلم أن المعاملات يجب أن تكون قصيرة قدر الإمكان ، ولكن يمكنك أن ترى أعلاه أن المعاملة قصيرة فقط مثل سرعة المستخدم الذي يملأ النموذج.

إذا كنت أستخدم مكونات غير مدركة للبيانات ، فسأقوم بعمل SQLs مخصصة على أساس إدخال المستخدم ، ثم قم بتنفيذ SQL بين StartTransaction والالتزام. حتى أتمكن من تحقيق معاملة قصيرة جدًا.

تحرير 2

أشكركم جميعًا على مشاركتك اللطيفة. اخترت الإجابة من VCLDeveloper لأنها أقرب حل إلى حاجتي الحالية.

هل كانت مفيدة؟

المحلول

ذكر آخرون باستخدام مجموعة من DatasetProvider و ClientDatAset للحصول على تحديث الدُفعات ، ولكن في حالة استخدام مكونات ADO أو UNIDAC ، لا تحتاج إلى طبقة إضافية من DataSetProvider + ClientDataset ، لأن كل من تحديثات الدفعة ADO و UNIDAC.

ل ado, ، ما يجب عليك فعله هو ضبط نوع القفل من مجموعة البيانات الخاصة بك إلى ltbatchoptimistic. ل Unidac, ، يجب عليك تعيين cacheupdate خاصية ل حقيقي.

يجعل هذا التغيير مجموعة البيانات الخاصة بك لتخزين جميع التغييرات التي تقوم بها على مجموعة السجلات في الذاكرة ، وإرسالها إلى قاعدة البيانات فقط عند الاتصال UpdateBatch الطريقة (ADO) أو applicipdates الطريقة (UNIDAC).

الآن ما يجب عليك فعله هو السماح للمستخدم بإدراج/تحرير سجل في مجموعة البيانات الرئيسية وأي سجلات يريدها في مجموعة بيانات التفاصيل باستخدام أي مكونات مدركة للبيانات تريدها. سيتم تخزين جميع التغييرات مؤقتًا. عند الانتهاء من المستخدم الخاص بك ، يمكنك بدء معاملة جديدة ، والاتصال الأول UpdateBatch (أو تطبيقها في حالة UNIDAC) لمجموعة البيانات الرئيسية ، ثم للحصول على بيانات بيانات التفاصيل ، وإذا سارت الأمور على ما يرام ، ارتكب المعاملة.

هذا سيجعل معاملاتك قصيرة دون الحاجة إلى طبقة إضافية من ClientDataset.

يعتبر

نصائح أخرى

أنا أفهم سؤالك ، على ما أعتقد. عند فتح tadodataset مع صفوف من البيانات 10 على سبيل المثال ليتم تحريرها على شكل ، مع مكونات مدركة للبيانات ، هناك حالات تريد فيها تخزين جميع التغييرات التي تم إجراؤها على جميع الصفوف العشرة (وربما الحذف والإدراج) وارتكابها كدفعة واحدة. لا يمكنك فتح المعاملة على التغيير الأول ، لأن ذلك سيمنع المستخدمين الآخرين تغيير البيانات نفسها. يجب أن تكون المعاملات قصيرة قدر الإمكان.

ما أقوم به في السيناريو المخطط هو استخدام المكونات التالية في السلسلة:

tadoconnection >> tadodataset >> tdatasetprovider >> tclientdataset >> tdatasource >> tdbedits الخ.

الآن يتم تخزين جميع التغييرات مؤقتًا في TclientDataset ويمكنك استدعاء طريقة تطبيقها لنشر جميع التغييرات في معاملة سريعة واحدة. ضع في اعتبارك أنه من الممكن أيضًا استخدام TadodataSets متعددة و TclientDatasets متعددة لهيكل Master Detail (-Detail-ETC) مع مجموعات بيانات متداخلة. قد يتم أيضًا تخزين جميع تغييرات Master Detail وتطبيقها في دفعة واحدة في معاملة واحدة. انظر المساعدة والموارد في مكان آخر للحصول على كل التفاصيل حول تنفيذ هذا. في البداية ، ليس من السهل. ولكن إذا اكتشفت ذلك ، فسيكون الأمر سهلاً ويوفر الكثير من الاحتمالات. (التحرير غير المتصل ، وفحص التغييرات قبل تطبيقها ، وما إلى ذلك)

لتجنب الحاجة إلى إجراء معاملات كبيرة أستخدمها DatasetProviders و ClientDataSets (حتى محليا).

فكر في استخدام هذا كنوع من ذاكرة التخزين المؤقت ويمنحك أفضل ما في العالمين. يمكنك استخدام عناصر تحكم مدركة للبيانات لتبسيط الأشياء أثناء العمل على واجهة المستخدم. يتم "تسجيل" إجراءات المستخدم عبر مجموعات البيانات من قبل ClientDatasets (نوع من ذاكرة التخزين المؤقت لقاعدة البيانات).

عندما يكون المستخدم مستعدًا ل حفظ التغييرات على قاعدة البيانات (على سبيل المثال ، بيانات الفاتورة كلها معمول بها) ، يمكنك الاتصال applicipdates طريقة لمجموعة البيانات (مجموعات).

في أبسط السيناريو ، حيث تكون جميع مجموعات البيانات في علاقة Master Detail (المتداخلة من قبل المزود) ، يبدأ الموفر ويرتبط/يرسل المعاملة بمفرده ، لذلك أنت في حالة كل شيء أو لا شيء تلقائيًا.

إذا كان لديك علاقات أكثر تعقيدًا ، فيمكنك استدعاء StartTransaction قبل البدء في تطبيق التحديثات لكل مجموعات ClientDataset المعنية ، وفي نهاية المكالمة أو التراجع حسب الحاجة). المنطق الخاص بالمزود هو إذا كان الاتصال به معاملة نشطة عند استدعاء ApplicuPdates ، فهو لا يفعل شيئًا مع المعاملة ، ولكن ببساطة نشر التغييرات على قاعدة البيانات ، على افتراض أنك تتحكم في المعاملة.

عليك أن تقرأ عن tclientdataset وكيفية التعامل مع onreconcileerror وتجربة التكنولوجيا قبل وضعها في بيئات الإنتاج ، لكنها تعمل بشكل جيد للغاية بالنسبة لي.

بلدي 2 سنت.

أنت محق تمامًا في أن أ اكتب يجب أن تكون المعاملة قصيرة قدر الإمكان ، ويجب ألا تكون على قيد الحياة طوال الوقت بينما يقوم المستخدم بملء النموذج.

الحل العام ، كما تم الإجابة عليه بالفعل ، هو استخدام طبقة وسيطة (عميل dataset). لكن المشكلة الحقيقية في السيناريو الخاص بك هي أنه لا يمكنك الحصول على قيمة تلقائية للجدول الرئيسي بدون Master.Append و Master.post ، وبالتالي تبدأ أ اكتب المعاملة قبل فترة طويلة من الحاجة فعلا.

لذلك إذا كنت لا ترغب في استخدام الطبقة المتوسطة ولا تزال تستخدم مكونات مدركة للبيانات مع قصيرة اكتب المعاملات التي يجب أن تفكر في قاعدة بيانات تدعم الحصول على قيمة تلقائية دون تنفيذ إدراج (إلى جدول ماجستير). المثال هو فايربيرد قاعدة البيانات ، ومكونات الوصول إلى البيانات fibplus لـ Firebird تدعم هذه الميزة بالكامل.

يجب أن تكون المعاملات قصيرة مثل ضروري. المشكلة هي كيف تتعامل قواعد البيانات المختلفة مع قفل. قواعد البيانات التي تؤدي فقط قفل على مستوى الصف ويمكن أن تعود على الفور من قفل دون الانتظار لديها احتمالية أقل بكثير إلى طريق مسدود. عادةً ما تكون الإدراج أقل إشكالية (على الرغم من أن المستخدم الآخر لن يشاهد صفوفًا جديدة حتى يتم التزامه ، اعتمادًا على مستوى العزلة) ، فإن التحديثات والحذف أكثر إشكالية. الالتزام في كثير من الأحيان يمكن أن يكون "سيئا" كذلك. يعد التخزين المؤقت لتغييرات وتطبيقها في عمليات واحدة احتمالًا آخر - ولكن عليك التعامل مع المشكلات بسبب تغيير المستخدمين الآخرين في الوقت نفسه. لا يوجد حل "أفضل" - كل شيء يعتمد على الاحتياجات الفعلية. بالنسبة لبعض التطبيقات (وبعض قواعد البيانات) الحفاظ على السجل مغلق طالما أنها تتغير على ما يرام ، قد لا يكون ذلك كذلك. قد تكون تحديثات الدُفعات على ما يرام في بعض السيناريوهات وليس في الآخرين. يجب عليك تحديد النموذج الذي يعمل بشكل أفضل لتطبيقك وقاعدة البيانات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top