24-10-2012, 03:05 PM
السلام عليكم...
بما أنك تتعامل مع جدولين لهما علاقة ببعضهما فيجب وضع عمليات الحفظ (و غيرها) ضمن صفقة (Transaction) بحيث يتم الحفظ في كلا الجدولين أو تلغى العملية في كلا الجدولين معاً.
أتصور أن جدول التفاصيل (facprod) يحتوي على عمود أو حقل لرقم الفاتورة من الجدول الرئيسي (fac). بمعنى أن كل سجل سيحفظ في جدول التفاصيل سيحتاج إلى رقم الفاتورة أو السجل المرتبط به في الجدول الرئيسي.
إذا كان البرنامج على جهاز واحد (مستخدم واحد للبرنامج، و ليس على شبكة) فإن الأمر سهل:
1. احفظ بيانات الجدول الرئيسي.
2. باستعمال استعلام (Query) احصل على رقم الفتورة أو السجل الجديد الذي حفظته.
3. احفظ سجلات الجدول الفرعي (المنتجات).
المشكلة الوحيدة - و هي محلولة - هي أنه ربما لسبب ما تحفظ البيانات في الجدول الرئيسي ثم يحدث خطأ أو خلل قبل أت تحفظ سجلات التفاصيل! و الحل كما ذكرنا أعلاه يكمن في استخدام الـ Transaction:
* إذا كنت تستخدم مكونات BDE فيجب أن يرتبط كلا الجدولين بمكون TDatabase واحد، ثم نستخدم الوظيفة StartTransaction لفتح الصفقة (Transaction) ثم الوظيفة Commit لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة Rollback لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.
* إذا كنت تستخدم مكونات ADO فيجب أن يرتبط كلا الجدولين بمكون TADOConnection واحد، ثم نستخدم الوظيفة BeginTrans لفتح الصفقة (Transaction) ثم الوظيفة CommitTrans لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة RollbackTrans لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.
فيما يلي كود عام بالخطوات الأساسية:
* طبعاً id_field هو اسم حقل المفتاح الأساسي في الجدول الرئيسي، و fac_table هو اسم الجدول الرئيسي في قاعدة البيانات.
نرجو الاستفادة و السلام.
بما أنك تتعامل مع جدولين لهما علاقة ببعضهما فيجب وضع عمليات الحفظ (و غيرها) ضمن صفقة (Transaction) بحيث يتم الحفظ في كلا الجدولين أو تلغى العملية في كلا الجدولين معاً.
أتصور أن جدول التفاصيل (facprod) يحتوي على عمود أو حقل لرقم الفاتورة من الجدول الرئيسي (fac). بمعنى أن كل سجل سيحفظ في جدول التفاصيل سيحتاج إلى رقم الفاتورة أو السجل المرتبط به في الجدول الرئيسي.
إذا كان البرنامج على جهاز واحد (مستخدم واحد للبرنامج، و ليس على شبكة) فإن الأمر سهل:
1. احفظ بيانات الجدول الرئيسي.
2. باستعمال استعلام (Query) احصل على رقم الفتورة أو السجل الجديد الذي حفظته.
3. احفظ سجلات الجدول الفرعي (المنتجات).
المشكلة الوحيدة - و هي محلولة - هي أنه ربما لسبب ما تحفظ البيانات في الجدول الرئيسي ثم يحدث خطأ أو خلل قبل أت تحفظ سجلات التفاصيل! و الحل كما ذكرنا أعلاه يكمن في استخدام الـ Transaction:
* إذا كنت تستخدم مكونات BDE فيجب أن يرتبط كلا الجدولين بمكون TDatabase واحد، ثم نستخدم الوظيفة StartTransaction لفتح الصفقة (Transaction) ثم الوظيفة Commit لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة Rollback لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.
* إذا كنت تستخدم مكونات ADO فيجب أن يرتبط كلا الجدولين بمكون TADOConnection واحد، ثم نستخدم الوظيفة BeginTrans لفتح الصفقة (Transaction) ثم الوظيفة CommitTrans لإنهاء الـ Transaction و حفظ البيانات في كلا الجدولين معا، أو الوظيفة RollbackTrans لإنهاء الـ Transaction و إلغاء عملية الحفظ من كلا الجدولين معا في حالة حدوث خطأ.
فيما يلي كود عام بالخطوات الأساسية:
كود :
var NewID: Integer;
// ...
try
Database1.StartTransaction; // بداية الصفقة
fac.Append;
// ...
// جمل تسجيل بيانات الجدول الرئيسي
// ...
fac.Post;
// الحصول على رقم السجل الجديد
Query1.SQL.Text := 'SELECT MAX(id_field) AS MaxID FROM fac_table';
Query1.Open;
NewID := Query1.FieldByName('MaxID').AsInteger;
// ربما هنا بداية حلقة أو ما شابه لتسجيل المنتجات
facprod.Append;
// ...
// جمل تسجيل بيانات الجدول الفرعي
// ...
facprod.Post;
// نهاية الحلقة
if Database1.InTransaction then
Database1.Commit; // اعتماد البيانات في كلا الجدولين و إنهاء الصفقة
except
if Database1.InTransaction then
Database1.Rollback; // التراجع عن كل التغييرات في كلا الجدولين و إنهاء الصفقة
ShowMessage('خطأ في حفظ البيانات');
end;* طبعاً id_field هو اسم حقل المفتاح الأساسي في الجدول الرئيسي، و fac_table هو اسم الجدول الرئيسي في قاعدة البيانات.
نرجو الاستفادة و السلام.

