بعضنا مر بتجربة مع تقنيات قديمة تخص تطبيقات الويب و هؤلاء فقط من يستطيعون تقدير العناء الذي يواجهنا عند محاولة إظهار بيانات لتصنيفات عامة مثل أقسام متجر ثم محاولة عرض فروع كل تصنيف تحته مباشرة و لعل أبسط طريقة كانت تحتاج لدالة إضافية كي تستخرج السجلات المرتبطة بجدول التصنيفات عن طريق مفتاح وحيد Primary Key في جدول التصنيفات و لكن مع تقنية الدوت نت وجدنا العديد من الميزات التي تجعلنا نقوم بعملنا بطريقة سهلة و مرنة للغاية دون الحاجة لذاك التعب و ذلك من خلال مفهوم يطلق عليه Relationships between DataTables و لكن كيف يكون ؟ هذا ما سنراه في هذا المثال المهم جدا و الذي سأشرحه بعد طرح المثال :
// C# Code :
string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("db.mdb");
string SQL="SELECT * FROM Categories";
OleDbConnection cn = new OleDbConnection(prov);
OleDbDataAdapter da = new OleDbDataAdapter(SQL,cn);
DataSet ds = new DataSet();
cn.Open();
da.Fill(ds,"Categories");
da.SelectCommand = new OleDbCommand("Select * From Lessons",cn);
da.Fill(ds,"Lessons");
// Add the relationship :
ds.Relations.Add("categories_lessons",
ds.Tables["Categories"].Columns["id"],
ds.Tables["Lessons"].Columns["catID"]);
// Display each Category with its Lessons :
foreach(DataRow row in ds.Tables["Categories"].Rows)
{
output.Text=output.Text + "<h3>" + row["category"] + "</h3>";
foreach(DataRow childRow in row.GetChildRows("categories_lessons"))
{
output.Text=output.Text + "<li>" + childRow["title"] + "</li>";
}
}
// VB.NET Code :
Dim prov As String
Dim SQL As String
Dim cn As OleDbConnection
Dim Ds As DataSet
Dim da As OleDbDataAdapter
prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" & Server.MapPath("db.mdb")
SQL="SELECT * FROM Categories"
cn = new OleDbConnection(prov)
da = new OleDbDataAdapter(SQL,cn)
ds = new DataSet
cn.Open()
da.Fill(ds,"Categories")
da.SelectCommand = new OleDbCommand("Select * From Lessons",cn)
da.Fill(ds,"Lessons")
// Add the relationship :
ds.Relations.Add("categories_lessons", _
ds.Tables("Categories").Columns("id"), _
ds.Tables("Lessons").Columns("catID"))
// Display each Category with its Lessons :
Dim row As DataRow
Dim ChildRow As DataRow
For Each row in ds.Tables("Categories").Rows
output.Text=output.Text & "<h3>" & row("category") & "</h3>"
For Each childRow in row.GetChildRows("categories_lessons")
output.Text=output.Text & "<li>" & childRow("title") & "</li>"
Next
Nextطبعا سيكون الناتج كالتالي :

في الأول نحتاج لأداة ويب من نوع Label و نعطيها الإسم output و هي التي ستخرج النتائج.
الان ما يلزمنا هو التالي :
1.عمل إتصال مع قاعدة البيانات.
2.عمل DataSet كقطعة في الذاكرة نخزن بها الجداول التي سنربط بينها.
3.إدراج جدول التصنيفات Categories في ال DataSet عن طريق إستدعاء الطريقة Fill الخاصة بال DataAdapter.
4.إدراج جدول الدروس التابعة للتنصيفات Lessons بنفس الطريقة السابقة لل DataSet نفسها.
5.إنشاء علاقة بين الجدولين المخزنين في ال DataSet.
6.عرض البيانات في واجهة التطبيق الخاصة بالمستخدم.
سأشرح الكود المكتوب بلغة ال #C و هو نفس الفكرة تماما في ال VB.NET .
بداية قمنا بعمل الإتصال و ملحقاته مثل ال DataAdapter :
string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("db.mdb");
string SQL="SELECT * FROM Categories";
OleDbConnection cn = new OleDbConnection(prov);
OleDbDataAdapter da = new OleDbDataAdapter(SQL,cn);قمنا بإنشاء قطعة ذكرة DataSet بإسم ds و بعدها فتحنا الإتصال مع مزود البيانات و قمنا بعمل تعبئة Fill في ال ds لجدول التصنيفات و قمنا بتخزينه باسم Categories كما هو هنا :
DataSet ds = new DataSet(); cn.Open(); da.Fill(ds,"Categories");
بعد ذلك قمنا بعمل إستعلام جديد من خلال تجديد ال SelectCommand الخاصة بال DataAdapter بحيث تستدعي السجلات الموجودة في جدول الدروس Lessons و قمنا بتخزين هذه السجلات في DataTable باسم Lessons في قطعة الذاكرة ال DataSet كما يلي :
da.SelectCommand = new OleDbCommand("Select * From Lessons",cn);
da.Fill(ds,"Lessons");الآن وصلنا للنقطة المهمة و هي إنشاء العلاقة بين الجدولين.
من المنطقي أن هناك علاقة بين الجدولين و بالعادة تكون من نوع one_to_many أو ما يطلق عليها 1-M مثلا عندنا PrimaryKey في جدول التصنيفات Categories بإسم id و يكون نفسه عبارة عن حقل مقحم في جدول الدروس Lessons عبارة عن ForeignKey بإسم CatID يربط الدرس بالتصنيف التابع له.
فكرة العمل تقوم على عمل علاقة برمجيا بين الجدولين نمرر لها 3 باراميترات الأول لإسم العلاقة و الثاني للمفتاح الرئيسي في جدول التصنيفات و الثالث للمفتاح المتعلق بالجدول الأول في الجدول الثالث كما يلي :
// Add the relationship :
ds.Relations.Add("categories_lessons",
ds.Tables["Categories"].Columns["id"],
ds.Tables["Lessons"].Columns["catID"]);طبعا الفكرة واضحة جدا.. قمنا بإستخدام الخاصية Relation و التي تخرج مجموعة علاقات بين البيانات أو الجداول من فئة DataRelation ثم استخدمنا الطريقة Add من أجل تمرير الباريمترات التي تحدثنا عنها قبل قليل.
الآن يبقى أن نقوم بعرض البيانات للمستخدم كما هو موضح هنا :
// Display each Category with its Lessons :
foreach(DataRow row in ds.Tables["Categories"].Rows)
{
output.Text=output.Text + "<h3>" + row["category"] + "</h3>";
foreach(DataRow childRow in row.GetChildRows("categories_lessons"))
{
output.Text=output.Text + "<li>" + childRow["title"] + "</li>";
}
}إستخدمنا دوارتين من نوع foreach الأولى تعرض الأقسام و الثانية تعرض الدروس التابعة لها و نستطيع الوصول للسجلات التابعة للسجل الأب كالتالي :
row.GetChildRows("categories_lessons")حيث استخدمنا خصائص المجموعة DataRows لنصل إلى الأبناء عن طريق GetChildRows ثم عرضنا البيانات.
أرفقت لكم الأكواد مع هذا الدرس .
محمد خليل أبو صلاح

