الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

العلاقات بين جداول البيانات Relationships

مغلق
بدأه محمد خليل أبو صلاح في 24 ديسمبر 2004 · 7 رد · 5,117 مشاهدة · في ASP.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بعضنا مر بتجربة مع تقنيات قديمة تخص تطبيقات الويب و هؤلاء فقط من يستطيعون تقدير العناء الذي يواجهنا عند محاولة إظهار بيانات لتصنيفات عامة مثل أقسام متجر ثم محاولة عرض فروع كل تصنيف تحته مباشرة و لعل أبسط طريقة كانت تحتاج لدالة إضافية كي تستخرج السجلات المرتبطة بجدول التصنيفات عن طريق مفتاح وحيد 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

طبعا سيكون الناتج كالتالي :

adonet-relations.gif

في الأول نحتاج لأداة ويب من نوع 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 ثم عرضنا البيانات.

أرفقت لكم الأكواد مع هذا الدرس .

محمد خليل أبو صلاح

ado-relations.zip

تم تعديل هذه المشاركة بواسطة محمد خليل أبو صلاح في 24 ديسمبر 2004 في 15:50

You can fly while you can touch the sky

#2

انا بجد يامحمد كنت محتاج مثل هذه الطريقة لانها تسهل علينا كتير 015

love36.jpg
#3

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

عموما شكرا لك عزيزي و على الرحب و السعة

You can fly while you can touch the sky

#4

السلام عليكم ،،،

جزاك اللــه خيرا أخي محمد خليل أبو صلاح .

كثر الله من أمثالك والله دروسك رائعة ومفيدة .

#5

بسم الله الرحمن الرحيم

مشكور أخوي محمد خليل علي المجهودات التي تبذلها في هذا المنتدي , جعلها الله لك في ميزان حسناتك

أود أن أطرح عليكم طريقة أخري لعمل نفس المهمة السابقة وذلك من خلال إستخدام Repeater Control كما يلي

<%@ Page Language="C#" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Data.OleDb" %>
<script runat="server">
    string prov;
    OleDbConnection cn;
    OleDbDataAdapter da;

    void Page_Load(object sender, EventArgs e) {
      this.prov = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("db.mdb");
      this.cn = new OleDbConnection(prov);

      string SQL = "SELECT * FROM Categories";
      da = new OleDbDataAdapter(SQL,cn);

      cn.Open();
      DataTable tb = new DataTable();
      da.Fill(tb);
      cn.Close();

      this.Repeater1.DataSource = tb;
      this.Repeater1.DataBind();
    }

    void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e) {
        System.Web.UI.WebControls.Repeater rep = e.Item.FindControl("Repeater2") as System.Web.UI.WebControls.Repeater;
        if( rep != null ) {
            string catID = ((DataTable)this.Repeater1.DataSource).Rows[e.Item.ItemIndex]["id"].ToString();

            string SQL="SELECT title FROM Lessons Where catID=" + catID;
            da = new OleDbDataAdapter(SQL,this.cn);

            cn.Open();
            DataTable tb = new DataTable();
            da.Fill(tb);
            cn.Close();

            rep.DataSource = tb;
            rep.DataBind();
        }
    }

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <asp:Repeater id="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
            <ItemTemplate>
                <h3><%# DataBinder.Eval( Container.DataItem, "Category")%></h3>
                <asp:Repeater id="Repeater2" runat="server">
                    <ItemTemplate>
                        <li><%# DataBinder.Eval( Container.DataItem, "title")%></li>
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </form>
</body>
</html>

وبالله التوفيق

والسلام عليكم

Rep.rar

1

29_5.gif

سورة العنكبوت

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

مشروع Arabic PHP.NET

حلم طالما كان يراودني حتي قهرته بحمد الله ليكون حقيقة

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

سلسلة أنماط التصاميم البرمجية Desgin Patterns

سلسلة أنماط التصاميم البرمجية Desgin Patterns | كتيب هذه الدروس (إعداد أحمد غريب)

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

كنترول ASP.NET DataGrid CheckBoxColumn

كنترول ProgressBar

كنترول UltraPanel

مشروع الكنترول الأنيق (إهداء للفريق العربي)

الورش الإلكترونية IT Workshops

تعقب الأخطاء error tracing

كنترول ColorPicker لمطوري الويب

RichTextBox Control لمطوري ال ASP.Net

حمل كتاب جافا سكربت عربي

#6

أخي الحسين هناك العديد من الطرق و ممكن استخدام اداتين او اداة مع ال Response.Write او ان نعتمد فقط على ال Response.Write و انا فقط كنت أطرح فكرة العلاقات التي اتاحتها ال ADO.NET من خلال ال DataSet

ولكن هناك ملاحظة على الكود الذي كتبته .. كيف سيقوم repeater2 بعرض البيانات ؟ لم تقم بربطه بالبيانات و لتصل لفكرة شبيهة بما كتبت انا تحتاج للتالي :

استخدام دالة تقوم بجلب البيانات من جدول الدروس و طبعا ستمرر لها رقم القسم الخاص بالدروس و هو من نوع PK و هذه هي الفكرة :

<%@ Page Language="C#" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.Data.OleDb" %>
<script runat="server">
   string prov;
   OleDbConnection cn;
   OleDbDataAdapter da;

   void Page_Load(object sender, EventArgs e) {
     this.prov = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("db.mdb");
     this.cn = new OleDbConnection(prov);

     string SQL = "SELECT * FROM Categories";
     da = new OleDbDataAdapter(SQL,cn);

     cn.Open();
     DataTable tb = new DataTable();
     da.Fill(tb);
     cn.Close();

     this.Repeater1.DataSource = tb;
     this.Repeater1.DataBind();
   }

   void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e) {
       System.Web.UI.WebControls.Repeater rep = e.Item.FindControl("Repeater2") as System.Web.UI.WebControls.Repeater;
       if( rep != null ) {
           string catID = ((DataTable)this.Repeater1.DataSource).Rows[e.Item.ItemIndex]["id"].ToString();

           string SQL="SELECT title FROM Lessons Where catID=" + catID;
           da = new OleDbDataAdapter(SQL,this.cn);

           cn.Open();
           DataTable tb = new DataTable();
           da.Fill(tb);
           cn.Close();

           rep.DataSource = tb;
           rep.DataBind();
       }
   }
 void GetLessons(int i)
  {
   OleDbConnection cn=new oleDbConnection("your provider here");
   string SQL="Select * From Lessons Where catID=@cID";
   OleDbCommand cmd=new OleDbCommand(,SQL,cn);
   cmd.Parameters.Add("@cID",i);
   cn.Open();
   OleDbDataReader reader=cmd.ExecuteReader();
  while(reader.Read())
    {
   Response.Write( "<li>" + reader("lesson") + "</li>");
  }
 reader.Close();
cn.Close();
  }

</script>
<html>
<head>
</head>
<body>
   <form runat="server">
       <asp:Repeater id="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
           <ItemTemplate>
               <h3><%# DataBinder.Eval( Container.DataItem, "Category")%></h3>
                                      <li><%# GetLessons(DataBinder.Eval( Container.DataItem, "catID"))%></li>
           </ItemTemplate>
       </asp:Repeater>
   </form>
</body>
</html>

و بهذه الطريقة لا تحتاج ل Repeater اخر ..

حظا موفقا و شكرا لكل من تفاعل منكم(f)

تم تعديل هذه المشاركة بواسطة محمد خليل أبو صلاح في 25 ديسمبر 2004 في 01:14

You can fly while you can touch the sky

#7

اسف جدا اخي الحسين .. الكود تبعك صحيح 100% لم انتبه جيدا للمتغير rep :D:$

سامحني رجاء و لك احلى وردة مني (f)

You can fly while you can touch the sky

#8

لا حرج عليك أخي محمد خليل

فلم يكن هدفي إلا إتاحة عرض طريقة أخري لعمل ذلك حتي تعم الفائدة للجميع , ولك مني كل الشكر علي مجهوداتك

والسلام عليكم

تم تعديل هذه المشاركة بواسطة الحسين في 25 ديسمبر 2004 في 02:42

29_5.gif

سورة العنكبوت

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

مشروع Arabic PHP.NET

حلم طالما كان يراودني حتي قهرته بحمد الله ليكون حقيقة

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

سلسلة أنماط التصاميم البرمجية Desgin Patterns

سلسلة أنماط التصاميم البرمجية Desgin Patterns | كتيب هذه الدروس (إعداد أحمد غريب)

ـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ

كنترول ASP.NET DataGrid CheckBoxColumn

كنترول ProgressBar

كنترول UltraPanel

مشروع الكنترول الأنيق (إهداء للفريق العربي)

الورش الإلكترونية IT Workshops

تعقب الأخطاء error tracing

كنترول ColorPicker لمطوري الويب

RichTextBox Control لمطوري ال ASP.Net

حمل كتاب جافا سكربت عربي

هذا الموضوع مغلق.

مواضيع مشابهة