وسائل
الفئة DataSet:
وقد استخدمنا هذه الوسيلة في الزر "حفظ
البيانات في ملف" في المشروع DataSetSample، وأرسلنا إلى المعامل الثاني القيمة WriteSchema لحفظ المخطط مع البيانات.. هذا يضمن لنا حفظ العلاقة بين الجدولين
والقيود المفروضة عليهما، والمفاتيح الأساسية والفرعية.
محو Clear:
تمحو كل السجلات من كل جداول مجموعة البيانات،
لكنها لا تمحو الجداول نفسها، ولا العلاقات بينها.. لاحظ أن هذه الوسيلة ستسبب خطأ
في البرنامج لو كانت مجموعة البيانات تتعامل مع وثيقة XML من النوع XmlDataDocument.
تصفير Reset:
تفرغ مجموعة البيانات من جميع محتوياتها، بما في
ذلك الجداول والعلاقات والقيود.
نسخ Clone:
تنسخ تركيب مجموعة البيانات (مخططات الجداول،
والعلاقات والقيود) إلى مجموعة بيانات جديدة وتعيد مرجعا إليها.. لكنها لا تنسخ أي
سجلات.
نسخ Copy:
تنسخ مجموعة البيانات كاملة (مخططات الجداول،
والعلاقات والقيود والسجلات أيضا) إلى مجموعة بيانات جديدة وتعيد مرجعا إليها.
معرفة التغيرات GetChanges:
تعيد مجموعة بيانات جديدة، تحتوي جداولها على
الصفوف التي تمّ تعديلها أو إضافتها أو حذفها منذ ملء مجموعة البيانات الأصلية، أو
منذ آخر استدعاء للوسيلة AcceptChanges.. وتعيد هذه الوسيلة Nothing إذا لم تجد أية تغيرات في مجموعة البيانات.
لاحظ أن هذه الوسيلة قد تضيف إلى مجموعة
البيانات الجديدة بعض الصفوف التي لم تتغير بياناتها، وذلك للمحافظة على صحة
العلاقات والقيود بين الجداول، ما يتيح لك إعادة دمج مجموعة البيانات الجديدة
بمجموعة البيانات الأصلية إذا أردت، دون حدوث أية أخطاء.
وتوجد صيغة ثانية لهذه الوسيلة، تستقبل إحدى قيم
المرقم DataRowState، التي تمكنك من الحصول على السجلات التي حدث بها نوع محدد من
التغيير دون سواه.. وهذه القيم هي:
مستقلّ
Detached
|
تمّ إنشاء هذا السجلّ ولكنه لم يوضع بعد في مجموعة
السجلات Rows الخاصة بأي جدول، أو أنه حذف
للتو من مجموعة سجلات أحد الجداول.
|
لم يتغير
Unchanged
|
لم تتغير بيانات هذا السجلّ، منذ أن تمّ تحميله من
قاعدة البيانات أو منذ آخر استدعاء للوسيلة AcceptChanges.
|
مُضاف
Added
|
هذا السجلّ ليس موجودا في قاعدة البيانات، وإنما تمّت
إضافته كسجل جديد إلى مجموعة البيانات.
|
محذوف
Deleted
|
تمّ حذف هذا السجلّ من مجموعة البيانات، ولكنه ما زال
موجودا في قاعدة البيانات.
|
معدّل
Modified
|
تمّ تعديل هذا السجلّ، ولكن لم يتمّ حفظ التعديلات في
قاعدة البيانات بعد.
|
ويمكنك دمج أكثر من قيمة من قيم هذا المرقم معا،
باستخدام المعامل OR.
تم تغييرها HasChanges:
تعيد True، إذا كانت مجموعة البيانات تحتوي على سجلات قد تم تعديلها أو
إضافتها أو حذفها، ولم تحفظ بعد في قاعدة البيانات.
ويمكنك استخدام هذه الوسيلة في حدث إغلاق
النموذج FormClosing، لسؤال المستخدم إن كان يريد حفظ البيانات قبل إغلاق البرنامج أم
لا، وهو ما فعلناه في المشروع CustomDataSet.. وقد استخدمنا هذه الوسيلة في الزر "تحميل من قاعدة
البيانات" في المشروع DataSetSample، لحفظ أية تغييرات قبل إعادة تحميل البيانات.
وتوجد صيغة ثانية لهذه الوسيلة، تستقبل إحدى قيم
المرقم DataRowState التي تعرفنا عليها من قبل.. وتعيد هذه الصيغة True إذا كانت مجموعة البيانات تحتوي على سجلات وقع عليها نوع التغيير
المرسل كمعامل.. والجملة التالية تخبرك إن كانت هناك سجلات جديدة أضيفت إلى مجموعة
البيانات أم لا:
MsgBox(Ds.HasChanges(DataRowState.Added))
قبول التغييرات AcceptChanges:
تجبر كل جداول مجموعة البيانات على استدعاء
الوسيلة AcceptChanges الخاصة بها.
رفض التغييرات RejectChanges:
تجبر كل جداول مجموعة البيانات على استدعاء
الوسيلة RejectChanges الخاصة بها.
إنشاء قارئ بيانات CreateDataReader:
تعيد قارئ بيانات الجداول DataTableReader، الذي يمكنك من خلاله المرور عبر سجلات كل جداول مجموعة البيانات.
وتنشئ هذه الوسيلة مجموعة نتائج ResultSet لكل جدول، بنفس ترتيب الجداول في مجموعة الجداول DataSet.Tables، وإذا كان أحد الجداول خاليا من السجلات، فستوضع مقابله في قارئ
البيانات مجموعة نتائج فارغة، وذلك للحفاظ على الترتيب.. ويمكنك الانتقال من قراءة
سجلات جدول إلى سجلات الجدول التالي باستخدام الوسيلة NextResult الخاصة بقارئ البيانات كما تعلمنا من قبل.
وتوجد صيغة ثانية لهذه الوسيلة تتيح لك التحكم
في ترتيب النتائج، حيث تستقبل مصفوفة جداول DataTable
Array، تحتوي على جداول مجموعة
البيانات التي تريد أن تقرأها، مع ملاحظة أن الجدول الذي يظهر في هذه المصفوفة
أولا سيعرض قارئ البيانات سجلاته أولا.
ويريك الزر "إنشاء قارئ بيانات" كيف
يمكنك استخدام هذه الوسيلة لعرض كل محتويات مجموعة البيانات في نافذة المخرجات Output
Window.
تحميل Load:
تتيح لك هذه الوسيلة استخدام قارئ البيانات DataReader لإضافة المزيد من السجلات إلى مجموعة البيانات.. ولهذه الوسيلة
ثلاث صيغ:
1- الصيغة
الأولى تستقبل ثلاثة معاملات:
- إحدى قيم المرقم LoadOption
التي تحدد ماذا سيحدث إذا كانت بعض السجلات موجودة سابقا في مجموعة البيانات، وهل
سيتم تحديث النسخة الأصلية من السجل Original Version أم النسخة الحالية Current Version.. وقد تعرفنا على هذا المرقم في الفصل السابق.
- مصفوفة جداول DataTable Array، تحتوي على بعض الجداول الموجودة في مجموعة الجداول DataSet.Tables، ليتم ملؤها بالسجلات من قارئ البيانات، حيث ستوضع سجلات كل
مجموعة من النتائج ResultSet
في الجدول المناظر لها في الترتيب في المصفوفة.
2-
الصيغة
الثانية مماثلة للصيغة السابقة، إلا أن معاملها الثالث يستقبل مصفوفة نصية تحتوي
على أسماء الجداول بدلا من كائنات الجداول.
3- الصيغة الثالثة تزيد بمعامل إضافي على الصيغة
الأولى.. هذا المعامل يأتي في الموضع الثالث في ترتيب المعاملات، وهو مندوب Delegate من النوع FillErrorEventHandler، وهو المندوب المستخدم في تعريف الحدث FillError الخاص بموصل البيانات.. ويمكنك أن ترسل إلى هذا المندوب عنوان
إجراء مناسب، ليتم استدعاؤه لو حدث خطأ عند إضافة أحد السجلات إلى مجموعة
البيانات.
دمج Merge:
تمزج بعض السجلات بسجلات مجموعة البيانات..
والمزج يعني أنّ السجلات الجديدة ستتمّ إضافتها إلى مجموعة البيانات، أمّا السجلات
الموجودة سابقا، فسيتمّ وضع السجلات المضافة بدلا منها..
وتتم مطابقة السجلات من خلال المفتاح الأساسي لكل منها، لهذا يجب أن يحتوي جدول
مجموعة البيانات على مفتاح أساسي، وإلا أدت عملية الدمج إلى تكرار نفس الصفوف
مرتين.
ولهذه الوسيلة العديد من الصيغ:
1-
بعض الصيغ ذات معامل واحد، يستقبل البيانات المراد مزجها، سواء كانت قادمة من
مجموعة بيانات DataSet، أو جدول DataTable أو مصفوفة سجلات DataRow
Array.
2- بعض الصيغ تزيد على الصيغ السابقة بمعامل ثان، إذا
جعلته True فستحتفظ مجموعة البيانات الأصليّة بالنسخة الحالية للسجلات، وسيتم المزج فقط على مستوى النسخة الأصلية...
دعنا نفهم هذا بمثال صغير: افترض أن لدينا سجلا في مجموعة البيانات، فيه خانة
قيمتها الأصلية 1، وقيمتها الحالية 2.. نريد أن نمزج هذا السجل بسجل مماثل له، لكن
القيمة الأصلية لهذه الخانة فيه هي 3، وقيمتها الحالية هي 4.. لو كانت قيمة هذا
المعامل True،
فستصير القيمة الأصلية لهذه الخانة في مجموعة البيانات بعد المزج 3، لكن ستظل
قيمتها الحالية 2.. أما إذا جعلت قيمتها False، فستصير القيمة الأصلية لهذه الخانة في مجموعة البيانات بعد المزج
3، وقيمتها الحالية 4.. الجدول التالي يلخص هذا المثال:
|
القيمة
الأصلية
|
القيمة
الحالية
|
سجل
مجموعة البيانات
|
1
|
2
|
السجل
الممزوج
|
3
|
4
|
سجل
مجموعة البيانات بعد المزج
(قيمة
المعامل True)
|
3
|
2
|
سجل
مجموعة البيانات بعد المزج
(قيمة
المعامل False)
|
3
|
4
|
لاحظ أن جعل هذا
المعامل True،
هو الطريقة الوحيدة التي تستطيع بها تغيير القيمة الأصلية دون تغيير القيمة
الحالية، لأن صيغ الوسيلة DataRow.Item التي تتيح لك تحديد النسخة التي تتعامل معها، قابلة للقراءة فقط،
ولا يمكن استخدامها للكتابة!
وقد استخدمنا الوسيلة Merge في المشروع OptimisticConcurrency مرتين:
- مرة في
حدث ضغط القائمة الموضعية "أريد حفظ تعديلاتي"، وقد أرسلنا إلى المعامل
الثاني لهذه الوسيلة القيمة True لتغيير النسخة الأصلية للسجل المراد إعادة حفظه، مع الاحتفاظ
بتغييرات المستخدم لحفظها في قاعدة البيانات.
- ومرة في
حدث ضغط القائمة الموضعية "إلغاء تعديلاتي"، وقد أرسلنا إلى المعامل
الثاني لهذه الوسيلة القيمة False للتخلص من السجل القديم، ووضع السجل القادم من قاعدة البيانات
بدلا منه (يشمل هذا النسخة الأصلية والنسخة الحالية للسجل).
3-
بعض الصيغ تزيد على الصيغ السابقة بمعامل ثالث، يحدد ردّ الفعل
الذي سيتخذ لو كان تركيب مجموعتي البيانات مختلفا (كعدم وجود بعض الجداول أو
الأعمدة في مجموعة البيانات الحالية)، وهو يأخذ إحدى قيم المرقم MissingSchemaAction.. تذكر أن القيمة الافتراضية في
الصيغ التي لا تستقبل هذا المعامل هي Add، بمعنى إضافة الجداول والأعمدة اللازمة إلى مجموعة البيانات الحالية لاستقبال البيانات الجديدة من مجموعة البيانات المضافة.
ولا يتمّ التحقق من صحّة القيود Constrains، إلا بعد اكتمال عمليّة المزج.. فإذا كانت هناك
سجلات تعارض القيود المفروضة، يحدث ما يلي:
- ينطلق خطأ
في البرنامج من النوع ConstraintException.
- توضع
القيمة False في الخاصية DataSet.EnforceConstraints لإيقاف تطبيق القيود، وذلك حتى يمكن الاحتفاظ بالبيانات الممزوجة
إلى أن ترى كيف تحل المشكلة.
- يوضع نص الخطأ في الخاصية RowError الخاصة بكل سجل يتعارض مع القيود المفروضة، لهذا عليك فحص هذه
الأخطاء وإصلاحها بالطريقة المناسبة، قبل محاولة وضع القيمة True في الخاصية EnforceConstraints من جديد لتطبيق القيود.
تخمين المخطط InferXmlSchema:
تقرأ كود XML، وتحاول استنتاج مخططات الجداول من بيانات السجلات الموجودة فيها،
وتحمّل هذا المخطط في مجموعة البيانات.. ولهذه الوسيلة عدة صيغ، كل منها لها
معاملان:
- المعامل
الأول يحدد الملف الذي يوجد به كود XML، سواء كان ذلك في صورة مسار الملف، أو كائن مجرى بيانات Stream، أو قارئ نصي TextReader، أو "قارئ XML" XmlReader.
- المعامل
الثاني يستقبل مصفوفة نصية، تحتوي على أسماء عناوين المواقع Url التي تريد استبعادها عند استخلاص المخطط من الملف.
الحصول على كود المخطط GetXmlSchema:
تعيد نصا يحتوي على كود XML الذي يمثل مخطط الجداول الموجودة في مجموعة البيانات.
الحصول على الكود GetXml:
تعيد نصا يحتوي على كود XML الذي يمثل البيانات الموجودة في مجموعة البيانات.
كتابة كود المخطط WriteXmlSchema:
تحفظ كود XML الذي يمثل مخطط جداول مجموعة البيانات، في الملف المرسل إليها
كمعامل، سواء كان في صورة مسار الملف، أو كائن مجرى بيانات Stream، أو قارئ نصي TextReader، أو "قارئ XML" XmlReader.
وتوجد عدة صيغ لهذه الوسيلة تزيد على الصيغ السابقة
بمعامل ثان من نوع المندوب Converter(Of Type, String)، وهو يستقبل عنوان أي دالة لها معامل من النوع Type وتعيد String..
هذا مفيد إذا كانت مجموعة البيانات تحتوي على عمود يتعامل مع نوع بيانات مركب لا
يمكن تحويله إلى نص مباشرة، وفي هذه الحالة يمكنك كتابة دالة مناسبة توضح كيف يمكن
تحويل بياناته إلى نص، وترسلها إلى هذا المعامل.
كتابة الكود WriteXml:
مماثلة للوسيلة السابقة، إلا أنها تحفظ سجلات
مجموعة البيانات في ملف XML..
وهناك صيغة أخرى لهذه الوسيلة، لها معامل ثانٍ من نوع المرقم XmlWriteMode الذي يمتلك القيم التالية:
IgnoreSchema
|
كتابة
السجلات فقط بدون كتابة مخطط البيانات.. هذه هي القيمة الافتراضية.
|
WriteSchema
|
كتابة
السجلات ومخطط البيانات معا في الملف.
|
DiffGram
|
كتابة
كل محتويات مجموعة البيانات في الملف، بما في ذلك النسخة الأصلية Original
Version والحالية Current
Version لكل السجلات، حتى لو لم
تتغير النسخة الحالية للسجل عن النسخة الأصلية.
|
ملحوظة:
|
إذا
أردت حفظ السجلات التي تغيرت فقط، فعليك استخدام الوسيلة DataSet.GetChanges للحصول على مجموعة بيانات جديدة بها السجلات التي تغيرت فقط،
واستخدام الوسيلة WriteXml
الخاصة بهذه المجموعة الجديدة لحفظ سجلاتها.
|
قراءة كود المخطط ReadXmlSchema:
مماثلة للوسيلة WriteXmlSchema في معاملاتها، ولكنها تقوم بالوظيفة العكسية، حيث تقرأ المخطط من
ملف XML وتحمّله في مجموعة البيانات.. لاحظ أن هذه الوسيلة قد تتسبب في
حدوث أخطاء إذا كانت مجموعة البيانات تحتوي على مخطط بالفعل، لهذا عليك استدعاء
الوسيلة DataSet.Reset أولا لمحو كل بياناتها ومخططاتها أولا، قبل استدعاء الوسيلة ReadXmlSchema.
قراءة الكود ReadXml:
مماثلة للوسيلة السابقة، إلا أنها تقرأ بيانات
السجلات من ملف XML
وتحملها في مجموعة البيانات.. وهناك صيغة أخرى لهذه الوسيلة، لها معامل ثانٍ من
نوع المرقم XmlReadMode الذي يمتلك القيم التالية:
Auto
|
القيمة
الافتراضية.
|
Read
Schema
|
قراءة
السجلات، وقراءة المخطط إن وجد في الملف (يجب أن ترسل إلى المعامل الثاني
للوسيلة WriteXml
القيمة WriteSchema
ليتم حفظ المخطط مع البيانات، وبالتالي يمكنك قراءته).. وإذا كان بمجموعة
البيانات مخطط بالفعل، تتم إضافة الجداول الجديدة إليه، لكن خطأ سيحدث لو كانت
مجموعة البيانات تحتوي على جدول له نفس اسم جدول موجود في المخطط.
ويؤدي
طلب قراءة المخطط من ملف يحتوي على البيانات فقط، إلى عدم تحميل أي منهما في
مجموعة البيانات!
|
Ignore
Schema
|
قراءة
السجلات فقط، مع تجاهل أي مخطط موجود.
|
Infer
Schema
|
تتجاهل
أي مخطط في الملف، وتحاول استنتاج المخطط من بيانات السجلات، وتضيف المخطط
والسجلات إلى مجموعة البيانات.. ويحدث خطأ إذا كانت مجموعة البيانات تحتوي على
مخطط بالفعل، وكان يحتوي على عمود تتعارض تفاصيله مع عمود موجود في المخطط
المضاف.
|
Infer
Typed
Schema
|
مماثلة
للقيمة السابقة، إلا أنها تستنج نوع بيانات كل عمود، فإن فشلت تعتبر أن نوع
العمود String.
|
Diff
Gram
|
تقرأ
السجلات الأصلية والحالية من الملف، وذلك إذا كنت حفظتها فيه سابقا باستخدام
القيمة DiffGram..
وإذا كانت مجموعة البيانات تحتوي على سجلات بالفعل فستحتفظ بها، وستضاف إليها
السجلات الجديدة.
|
Fragment
|
استخدم
هذه القيمة إذا كان الملف يحتوي على أجزاء من كود XML وليس كود وثيقة كاملة.
|
وقد استخدمنا هذه الوسيلة في الزر "قراءة
البيانات من ملف" في المشروع DataSetSample، وأرسلنا إلى المعامل الثاني القيمة ReadSchema لقراءة المخطط مع البيانات.. هذا يضمن لنا إنشاء العلاقة بين
الجدولين في مجموعة البيانات، لأن وظيفة البرنامج تحتاجها.
لاحظ أن الوسيلة ReadXml لا تستدعي الوسيلة AcceptChanges تلقائيا كما تفعل الوسيلة DataAdapter.Fill، لهذا فإن السجلات التي يتم تحميلها في مجموعة البيانات ستعتبر
سجلات جديدة Addedd،
ولو ضغطت زر الحفظ في قاعدة البيانات، فسيتم إضافة كل هذه السجلات مرة أخرى إلى
جدول المؤلفين وجدول الكتب، وهذا سيجعل البيانات مكررة!.. ولحل هذه المشكلة، عليك
استدعاء الوسيلة AcceptChanges
مباشرة بعد تحميل السجلات إلى مجموعة البيانات، وبهذا يتم اعتبار أنها لم تتغير،
ولا يتم حفظها في مجموعة البيانات.
لكنك قد تريد اعتبار السجلات جديدة في بعض
المواقف، وذلك إذا كنت تملك البيانات في ملف XML وتريد إضافتها إلى قاعدة بيانات فارغة.
وهناك ملاحظة بسيطة أخرى، وهي أن هذه الوسيلة لا
يهمها امتداد الملف، بل يهمها فقط صحة محتوياته.. لهذا فقد أعطينا للملفات الخاصة
بنا في المشروع CustomDataSet
الامتداد .dsf، وهي امتداد من اختراعنا (اختصار للتعبير DataSet
Format)، وجعلنا مربع حوار فتح
ملف لا يعرض سوى الملفات التي لها هذا الامتداد، وبهذا نضمن أن الملفات التي نحاول
قراءتها سيكون لها الصيغة المناسبة لمجموعة البيانات، فملفات XML تستطيع حمل أي نوع من البيانات وبأي تنسيق، لكنها لن تكون جميعا
صالحة للعرض في برنامجنا.
من
كتاب: من الصفر إلى الاحتراف برمجة قواعد البيانات في فيجوال بيزيك دوت نت ADO .NET.. للتنزيل:
ليست هناك تعليقات:
إرسال تعليق
ملحوظة: يمكن لأعضاء المدونة فقط إرسال تعليق.