شاطر
اذهب الى الأسفل
عدد المساهمات : 134
تاريخ التسجيل : 08/10/2012
معاينة صفحة البيانات الشخصي للعضو

الوضع المتصل والوضع المنفصل - ربط DataGridView بجدول في الوضع المنفصل

في الخميس أكتوبر 10, 2013 4:53 pm
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة]

سنبدأ على بركة الله مع أول مثال من سلسلة الأمثلة المرفقة مع هذا الدرس. هذا المثال سيكون عبارة عن نموذج به مربع DataGridView نقوم بربطها مع الجدول UserInfo على قاعدة البيانات. تتم عملية تحميل البيانات وقت تشغيل التطبيق ثم نترك المستخدم يقوم بجميع العمليات المتاحة من زيادة و تحديث و حذف البيانات على الداتاجريدفيو و وقت غلق التطبيق ستتم عملية حفظ المعلومات رجوعا نحو الجدول على قاعدة البيانات. بهذه الطريقة سنكون قد قمنا بالتعامل مع قاعدة البيانات في الوضع المنفصل حيث أننا سنربط الإتصال بقاعدة البيانات وقت تشغيل التطبيق لتحميل البيانات, العمليات كلها ستتم على الذاكرة الحية (مجموعات DataRow) للجداول DataTable, ثم لنا عودة مع ربط الإتصال مرة أخرى مع قاعدة البيانات وقت غلق التطبيق لحفظ البيانات من الذاكرة الحية نحو قاعدة البيانات.

في الوضع المنفصل, نحتاج من البيانات المحملة من قاعدة البيانات أن تبقى على الذاكرة الحية. هذه البيانات تحتاج لحاوية لتجمعها و لتيسر علينا تسييرها, حاوية البيانات التي سنستعمل هي كائن من نوع DataSet الذي يمكننا أن نقول أنه سيكون نسخة على الذاكرة الحية طبق الأصل من قاعدة البيانات. و حتى تبقى البيانات متاحة طيلة مدة اشتغال التطبيق سنحتاج لتعريف كائن من نوع DataSet على مستوى النموذج Form :


الكود:

' الداتاست التي ستكون الحاوية للجداول التي سيملأها الكائن مايأدابتر
  Dim MyDataSet As DataSet

لتحميل البيانات من قاعدة البيانات نحو DataSet, سنحتاج إلى كائن من نوع OleDbDataAdapter. هذا الكائن سنحتاج إليه وقت تحميل البيانات وقت تشغيل التطبيق ثم سنحتاج إليه أيضا وقت عملية حفظ التغييرات التي تمت على البيانات من الذاكرة الحية نحو قاعدة البيانات. لهذا, سنقوم أيضا بتعريف الكائن على مستوى النموذج Form :

' كائن تحميل, تحرير, زيادة و حذف المعلومات
 

الكود:

' كائن تحميل, تحرير, زيادة و حذف المعلومات
  Dim MyAdapter As New OleDbDataAdapter



بعد تعريف الكائنين MyDataSet و MyAdapter, سنحتاج إلى تهيئتهما لنتمكن من تحميل البيانات و بما أننا سنقوم بتحميل البيانات وقت تشغيل التطبيق فكود التهيئة سنضعه داخل دالة الحدث Load للنموذج الرئيسي للتطبيق.
سنحتاج أولا لتحديد جملة الربط مع قاعدة البيانات :


الكود:

' جملة الربط
  Dim ConString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =.\AccessDB.mdb"


بعد ذلك, سنحتاج إلى إنشاء و تهيئة الكائن MyAdapter الذي يحتاج إلى جملة الربط مع قاعدة البيانات, أيضا جملة الاستعلام SQL SELECT التي سيقوم بتنفيذها وقت طلب تحميل البيانات. سنقوم أولا بإنشاء الكائن و ننادي على الباني الإفتراضي الذي يقبل جملة الاستعلام و جملة الربط :


الكود:

' تهيئة كائن جملة تحرير التسجيلات مع البرامترز
  MyAdapter.UpdateCommand = New OleDbCommand("UPDATE UserInfo SET [Login] = @Login, [Password] = @Password, GroupID = @GroupID WHERE ID = @ID", MyAdapter.SelectCommand.Connection)
  MyAdapter.UpdateCommand.Parameters.Add("@Login", OleDbType.WChar, 32, "Login")
  MyAdapter.UpdateCommand.Parameters.Add("@Password", OleDbType.WChar, 32, "Password")
  MyAdapter.UpdateCommand.Parameters.Add("@GroupID", OleDbType.BigInt, 1, "GroupID")
  MyAdapter.UpdateCommand.Parameters.Add("@ID", OleDbType.BigInt, 1, "ID")


جملة SQL UPDATE التي هيأنا بها الخاصية UpdateCommand يجب أن يتم فيها تحديد كل الحقول التي نريد من الكائن MyAdapter تحديثها و كل حقل نحدد له وسيط لتمرير القيمة الجديدة للحقل, نزيد الوسيط و هو كائن من نوع OleDbParameter إلى مجموعة الوسائط Parameters للكائن OleDbCommand عن طريق المناداة على الدالة Add. سنحتاج كذلك لشرط كفيل بتحديد التسجيل الذي سيتم تحديث قيمته دون المغامرة بتحديث تسجيلات أخرى عن طريق الخطأ. لهذا فلكل جدول على قاعدة البيانات AccessDB.mdb معرف وحيد غير قابل للتكرار بخاصية الترقيم التلقائي و معرف التسجيل هو الحقل ID. بهذه الطريقة, سنضمن أن المقطع WHERE ID = @ID سيقوم بتحديث التسجيل الوحيد المعرف بـ @ID لا غير.

عندما يجد الكائن MyAdapter سطر على الذاكرة الحية معلم عليه أنه قد تم حذفه, سيقوم بتنفيذ جملة SQL DELETE المحددة على الخاصية DeleteCommand بكائن من نوع OleDbCommand :


الكود:

' تهيئة كائن أمر الحدف مع البرمتر مرجع التسجيل المراد حذفه
  MyAdapter.DeleteCommand = New OleDbCommand("DELETE FROM UserInfo WHERE ID = @ID", MyAdapter.SelectCommand.Connection)
  MyAdapter.DeleteCommand.Parameters.Add("@ID", OleDbType.BigInt, 1, "ID")


لتحديد التسجيل الوحيد الذي سيتم حذفه دون المغامرة بحذف تسجيل آخر عن طريق الخطأ سنحدد الشرط WHERE لجملة الحذف بمعرف التسجيل و نحدد الوسيط @ID الذي سيستقبل المعرف.

عندما يجد الكائن MyAdapter سطرا على الذاكرة الحية غير موجود على قاعدة البيانات سيقوم بتنفيذ جملة SQL INSERT لزيادته على قاعدة البيانات. لتهيئة الكائن MyAdapter بإمكانية زيادة أسطر موجودة على الذاكرة الحية و غير موجودة على قاعدة البيانات, سنحتاج إلى تهيئة الخاصية InsertCommand بكائن من نوع OleDbCommand مهيئ بجملة SQL INSERT لتنفيذها وقت زيادة سطر جديد إلى قاعدة البيانات :


الكود:

' تهيئة كائن أمر زيادة التسجيلات من الداتاست إلى الجدول على قاعدة البيانات
  MyAdapter.InsertCommand = New OleDbCommand("INSERT INTO UserInfo ([Login], [Password], GroupID) VALUES(@Login, @Password, @GroupID)", MyAdapter.SelectCommand.Connection)
  MyAdapter.InsertCommand.Parameters.Add("@Login", OleDbType.WChar, 32, "Login")
  MyAdapter.InsertCommand.Parameters.Add("@Password", OleDbType.WChar, 32, "Password")
  MyAdapter.InsertCommand.Parameters.Add("@GroupID", OleDbType.BigInt, 1, "GroupID")


لتحديد البيانات التي ستتم تهيئة السطر الجديد بها, سنقوم بزيادة وسائط لكل حقل من حقول التسجيل إلا الحقل المعرف للتسجيل لأنه يتمتع بخاصية الترقيم التلقائي.

بعد أن أتممنا تهيئة الكائن MyAdapter, سنقوم بإنشاء و بتهيئة الكائن MyDataSet الذي سيستقبل البيانات التي سيقوم الكائن MyAdapter بتحميلها من قاعدة البيانات :


الكود:

' إنشاء و تهيئة الداتاست
  MyDataSet = New DataSet("AccessDB")


بعد عملية الإنشاء يمكننا أن نقوم بعملية تحميل البيانات من القاعدة :


الكود:

تحميل تسجيلا الجدول من قاعدة البيانات إلى الداتاست
  MyAdapter.Fill(MyDataSet, "UserInfo")


بعد تحميل البيانات, يمكننا ربط مربع DataGridView مع الجدول UserInfo الذي تم تحميل محتواه للتو :


الكود:

' ربط الداتاجريدفيو بالداتاست أي الوضع المنفصل
  DataGridView1.DataSource = MyDataSet.Tables("UserInfo")


السطر أعلاه كفيل وحده بملئ الداتاجريدفيو بمحتوى الجدول UserInfo. بما أن معرف التسجيل أي الحقل ID معرف على أن له خاصية الترقيم التلقائي فتغيير محتواه سيرفع استثناء و لتفادي ذلك سنقوم بحظر الكتابة على العمود الأول :


الكود:

' منع الكتابة على خلايا عمود المرجع
  DataGridView1.Columns(0).ReadOnly = True


إذا أنهينا مرحلة التهيئة في السطر الأخير, سنلاحظ أن العمود الأخير المخصص لإضهار المجموعة التي ينتمي إليها المستخدم يضهر أرقاما مكان اسم المجموعة. إذا تتذكرون بنية قاعدة البيانات التي نعمل عليها, سوف تتذكرون أن هناك جدول آخر GroupInfo به أسماء المجموعات و الذي سنقوم بربطه مع الجدول UserInfo عبر الحقل GroupID الذي يشير إلى مرجع التسجيل الذي يحتوي على اسم المجموعة. لإضهار أسماء المجموعات و تمكين المستخدم من تحديد و اختيار المجموعة التي ينتمي إليها المستخدم سوف نقوم بتحميل أسماء المجموعات على جدول في الذاكرة الحية DataTable و إنشاء عمود من نوع DataGridViewComboBoxColumn و تهيئته حتى تظهر مربعات ComboBox للعمود لائحة المجموعات للمستخدم وقت الاختيار و اسم المجموعة التي ينتمي إليها في الحالة العادية.
كما قمنا بذلك سابقا, سنقوم بنفس الطريقة بتحميل محتوى الجدول GroupInfo من قاعدة البيانات إلى الذاكرة الحية. سنقوم بإنشاء كائن جديد من نوع OleDbDataAdapter و نهيئه هذه المرة فقط بجملة SQL SELECT لأننا فقط سنقرأ مجموعات المستخدمين و لن نقوم بعمليات زيادة, تحديث أو حذف عليها. بعد ذلك سننادي على الدالة Fill لتحميل البيانات ثم نحرر الكائن لأننا لن نحتاج إليه مرة أخرى :


الكود:

' تحميل بيانات أسماء المجموعات
  Dim adptr As New OleDbDataAdapter("SELECT * FROM GroupInfo", MyAdapter.SelectCommand.Connection)
  adptr.Fill(MyDataSet, "GroupInfo")
  adptr.Dispose()



المرحلة القادمة من عملية التهيئة, سنقوم خلالها بحذف العمود الذي يظهر معرفات تسجيلات أسماء مجموعات المستخدمين بعمود آخر تكون كل خلية منه عبارة عن ComboBox تمكن المستخدم من اختيار مجموعة من بين المجموعات الموجودة على الجدول GroupInfo. سنقوم أولا بإنشاء عمود جديد من نوع DataGridViewComboBoxColumn :


الكود:

' العمود العادي المراد تغييره
  Dim OldColumn As DataGridViewTextBoxColumn = DataGridView1.Columns(DataGridView1.Columns.Count - 1)
  ' نسخ خصائص العمود الأصلي
  CmbColumn.Name = OldColumn.Name
  CmbColumn.DataPropertyName = OldColumn.DataPropertyName
  CmbColumn.HeaderText = OldColumn.HeaderText


بعد ذلك سنقوم بحذف العمود الأصلي و زيادة العمود الجديد مكانه :


الكود:

' حذف العمود القديم
  DataGridView1.Columns.Remove(OldColumn)
  ' زيادة عمود الكمبوبوكس
  DataGridView1.Columns.Add(CmbColumn)


و أخيرا, نقوم بربط العمود أو مربعات الكمبوبوكس للعمود بالجدول GroupInfo الموجود على الذاكرة الحية الذي سيظهر الحقل Name و يخزن على الجدول UserInfo الحقل GroupID.ID :


الكود:

' ربط العمود بجدول أسماء المجموعات
  CmbColumn.DataSource = MyDataSet.Tables("GroupInfo")
  CmbColumn.DisplayMember = "Name"
  CmbColumn.ValueMember = "ID"



الآن و قد قمنا بتحميل البيانات من القاعدة سيظهر النموذج الرئيسي و عليه مربع الداتاجريدفيو التي هي الآن غير مرتبطة بقاعدة البيانات و إنما بنسخة طبق الأصل عنها موجودة على الذاكرة الحية في شكل جداول DataTable تجمعها الحاوية DataSet.
نترك الآن المستخدم يقوم بعمله على البيانات التي تظهرها الداتاجريدفيو و تتيح للمستخدم إمكانية زيادة, تحديث و حذف أسطرها و كل هذه العمليات ستتم على الذاكرة الحية أما قاعدة البيانات فلنا معها عودة عندما يغلق المستخدم النموذج.

...

عندما يغلق المستخدم النموذج ستتم المناداة على دالة الحدث FormClosing التي سنقوم بزيادة كود حفظ التغييرات التي قام بها المستخدم على البيانات المتواجدة على الذاكرة الحية. الكود بسيط للغاية, نقوم بالمناداة على الدالة HasChanges للكائن MyDataSet الذي ترجع لنا true إذا ما قام المستخذم بعملية ما أدت إلى تغيير البيانات الموجودة على أحد جداول MyDataSet, في هذه الحالة نقوم بالمناداة على الدالة Update للكائن MyAdapter التي كما ذكرنا سابقا ستقوم بالتحقق من حالة البيانات الموجودة على الذاكرة الحية أي مجموعات DataRow المتواجدة داخل الجداول DataTable الذي مررناه إلى الدالة Update و تقوم بحذف الأسطر المحذوفة, زيادة الأسطر الجديدة و تحديث الأسطر التي تم بها تحديث للمحتوى :


الكود:

' إذا كانت هناك تغييرات
  If MyDataSet.HasChanges() Then
  ' حفظ التغييرات في جدول المستخدمين على قاعدة البيانات
  MyAdapter.Update(MyDataSet.Tables("UserInfo"))
  End If


أتمنى أن يكون المثال الأول قد أدى عمله و قد وضح طريقة الربط المنفصل بالنسبة لمربع DataGridView و سنرى في مثال لاحق مشروعا آخر بنفس طريقة الربط و لكن هذه المرة ستكون مربعات النص و الكومبوبوكس.

المثال التالي سيكون نفس المشروع الحالي و لكن الفرق بينه و بين هذا المثال سيكون في طريقة الربط بقاعدة البيانات التي ستكون بالطبع بالوضع المتصل.

يتبع...


_________________
[img][ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذا الرابط] [/img]
الرجوع الى أعلى الصفحة
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى