التنبيهات التالية ظهرت :
Warning [2] count(): Parameter must be an array or an object that implements Countable - Line: 864 - File: showthread.php PHP 7.4.33 (Linux)
File Line Function
/showthread.php 864 errorHandler->error



تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
مثال للتعامل مع الجداول المرتبطة - عن طريق الكلاسات
#1
بســـــــــــم الله الرحمن الرحيم


السلام عليكم و رحمة الله و بركاته
ابدأ معكم بمراجعة بسيطة بطرق تعاملنا مع الجداول وفق تقنية ADO.Net و اهم العمليات التي نحتاجها بشكل متكرر اثناء عملنا مع اي جدول , لا يخفى على الجميع و الكل يعرف اننا دائما و ابداً نحن امام الحالات التقليدية (الاضافة و التعديل و الحذف) كحالات رئيسة ترافق العمل مع اي جدول بالاضافة للحالات الاخرى حسب الحاجة من عمليات البحث او تجميع البيانات وفق اي نوع من الاستعلامات تفرضه علينا الحاجة .
و اعتدنا دائماً على التعامل مع الجمل التقليدية التي توافق كل حالة و على اعادة تكرارها مع كل مشروع .
و الذي يختلف فقط هو عدد الحقول و اسمائها و انواع بيانات الحقول فيها .
و هذا التكرار اشبه بعملية النسخ و اللصق و تغير ما يلزم وفق المعطيات التي يحملها المشروع الجديد

هذه المقدمة البسيطة ضرورية لنتجاوز التكرار او بالمختصر لنحول عملية النسخ و اللصق المعتادة الى طريقة عملية تجعلنا نستفيد من الثوابت في جمل الادخال و الاضافة و التعديل و البحث و غيرها من الجمل و نحولها الى دوال منفصلة نحتاج فيها فقط ما يتغير مع كل مشروع جديد , و بالتالي نفصلها في فئة خاصة بها بعيداً عن واجهة البرنامج (مثل مكتبة او اطار عمل) و عند حاجتنا لها نستدعي المكتبة و نغير فقط ما يسمح لنا بتغيره و بالتالي وفرنا على انفسنا عناء اعادة كتابة الجمل كل مرة.

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

اتمنى ان يكون كلامي مفهوم الى هذه اللحظة و ان شاء الله سيتضح مع التطبيق الذي سنبدئه و نناقش تطويره


في البداية ساعرض جملة الادخال المعروفة لديكم لنرى ما هي الثوابت فيها , ووفق شكلها القياسي التالي

PHP كود :
INSERT INTO table_name (column1,column2,column3,...)
VALUES (value1,value2,value3,...) 
كما هو واضح المتغيرات الجدول و الاعمدة و قيم هذه الاعمدة و باقي النص ثابت
و على هذا لو كان لدي مصفوفة من الاعمدة و القيم تمرر بدل هذه المتغيرات اكون قد ارتحت من اعادة كتابة نفس الجملة
هذا من طرف الجملة , اما من طرف اطار العمل سيكون لدي كائن يقوم بتنفيذ هذه الجملة و هذا الكائن يحتاج الى اتصال و يحتاج الجملة السابقة و يحتاج الى بارمترات موافقة لعدد الحقول و قيم لهذه البارمترات و في النهاية سيقوم بالتنفيذ بعد اكتفائه بالمعلوممات المطلوبة.
الان لننظر الى هذا الكود الخاص بهذا الكائن و لنكتشف ما يمكننا الاستفادة منه
كائن ينفذ عملية ادخال سجل جديد في جدول
PHP كود :
   Private Sub Insert_SomeData()
 
       Dim Insert_Statement As String "INSERT INTO table_name (column1,column2,column3) VALUES (@column1, @column2, @column3)"
 
       Using Cmd As New SqlClient.SqlCommand(Insert_StatementCon)
 
           Cmd.Parameters.AddWithValue("@column1"Txt_column1.Text)
 
           Cmd.Parameters.AddWithValue("@column2"Txt_column2.Text)
 
           Cmd.Parameters.AddWithValue("@column3"Txt_column3.Text)
 
           Con.Open()
 
           Cmd.ExecuteNonQuery()
 
           Con.Close()
 
       End Using
    End Sub 
بعد التمعن في الكود السابق سنرى ان اغلبها ثوابت تتكرر كل مرة باستثناء ما اشرنا اليه سابقا من اسم الجدول و قائمة الحقول و القيم الموافقة لتلك الحقول و التي يشترك فيها ايضاً الكائن (Command)  و حتى كائن الاتصال Con يعتبر ثابت ايضاً لاننا نعرف هذا الكائن غالباً على مستوى المشروع لذا سيكون الوصول اليه متاح من كل انحاء المشروع
اذاً ما علينا في هذه الحالة ان نمرر اسم الجدول كبارميتر لهذا الاجراء و كذلك نمرر اسماء الحقول و قيمها ايضاً كبارميتر عبر مصفوفة و نكون قد تحصلنا على اجراء ادخال عام يستطيع الادخال في اي جدول بمجرد استدعائه و تمرير وسائطه المطلوبة
و لو دققنا اكثر في الاجراء السابق الخاص بالاضافة سنرى انه ينفذ عملية في داخله و هي ExecuteNonQuery  و التي بدورها تعيد قيمة رقمية بعد تنفيذها فهي تعيد اما 0 او 1  نجاح او فشل التنفيذ و عليه يمكننا استغلال الرقم العائد و عرض رسالة في حال نجح او فشل , و عليه فاننه يمكننا تحويل الاجراء السابق الى دالة تعيد الرسالة .
و بمنطق اعمق , بما انني اضيف سجل جديد و فق الدالة السابقة فالاولى ان اتحصل على رقم السجل المضاف الى الجدول لاستفيد منه و بناءً على ذلك اريد ان اجري عملية اضافية بعد الادخال و هي تحصيل رقم السجل و فق الكود التالي
PHP كود :
           Cmd.CommandText "Select @@IDENTITY"
 
           Resuilt CType(Cmd.ExecuteScalar(), Integer
هكذا اصبحت الدالة عملية اكثر تقوم بعملية ادخال و من بعدها تعيد رقم السجل المضاف.
الى هنا ينتهي غرضي من هذا التقديم لانتقل بك الى الجزء التالي


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


يتبع...

في البداية ننشأ مشروع جديد 
نضيف كلاس للمشروع و نسميه DbGo او سميه ما شئت ستكون وضيفة هذا الكلاس تجميع كل ما نحتاجه من دوال و اجراءات عامة يمكن لكل الكائنات ان تستفيد منها و تعيد تطبيقها بما يناسبها

ساضيف لهذا الكلاس بعض التمهيدات الاولية كما يلي
PHP كود :
   Protected Shared MyConnectionString As String ""
 
   Protected Shared ConSql As New SqlClient.SqlConnection(MyConnectionString)


 
   Shared Sub New(ByVal ConnectionString As String)
 
       SetConnectionString ConnectionString
        If ConSql
.ConnectionString Nothing Then ConSql.ConnectionString MyConnectionString
    End Sub 

عند انشاء اي نسخة جديدة منه سيطلب منك تمرير نص الاتصال الخاص بالسيرفر


PHP كود :
   ''' <summary>
    ''' 
Set Or Get ConnectionString
    
''' </summary>
    ''' 
<returns></returns>
 
   Public Shared Property SetConnectionString() As String
        Set
(value As String)
 
           MyConnectionString value
        End Set
        Get
            Return MyConnectionString
        End Get
    End Property


    
''' <summary>
    ''' 
Close Connection To Data Base
    
''' </summary>
    Protected Shared Sub CloseConnect()
        If ConSql.State = ConnectionState.Open Then
            ConSql.Close()
        End If
    End Sub

    ''' 
<summary>
 
   ''' Open Connection To Datat Base
    ''' 
</summary>
 
   Protected Shared Sub OpenConnect()
 
       If ConSql.State ConnectionState.Closed Then
            If ConSql
.ConnectionString Nothing Then ConSql.ConnectionString MyConnectionString
            ConSql
.Open()
 
       End If
 
   End Sub 

خاصية لاسناد نص الاتصال او الحصول عليه و هي محصورة على الكائنات التي تشتق هذا الكلاس
اجراء لفتح الاتصال , و اجراء لغلق الاتصال

PHP كود :
   ''' <summary>
    ''' 
اضافة سجل جديد الى جدول
    
''' </summary>
    ''' 
<param name="TableName">اسم الجدول</param>
 
   ''' <param name="Table">الجدول الذي يحوي الحقول و قيمها وهو مصفوفة</param>
    ''' 
<param name="KeyFiled">اسم حقل المفتاح الرئيسي ليتم استثنائه من جملة الاضافة</param>
 
   ''' <param name="Msg">رسالة الاضافة وهي اختيارية</param>
    ''' 
<returns>يعود بقيمة الحقل المضاف للمفتاح الرئيسي</returns>
 
   Protected Function Add_New(ByVal TableName As StringByVal Table As Dictionary(Of StringObject), ByVal KeyFiled As StringOptional ByVal Msg As Boolean False) As Integer

        Dim Resuilt 
As Integer 0
        Dim Insert_Statement 
As String "insert Into " TableName " ("

 
       If Table.ContainsKey(KeyFiledThen
            Table
.Remove(KeyFiled)
 
       End If


 
       Dim Column As String String.Empty
 
       For X As Integer 0 To Table.Count 1
            Column 
Table.Keys.ElementAt(X)
 
           Insert_Statement += Column ","
 
       Next
        
'
        If Insert_Statement.EndsWith(",") Then Insert_Statement = Insert_Statement.Remove(Insert_Statement.Count - 1, 1)
        Insert_Statement += ")" & " Values ("
        '
 
       For X As Integer 0 To Table.Count 1
            Column 
Table.Keys.ElementAt(X)
 
           Insert_Statement += "@" Column ","
 
       Next

        If Insert_Statement
.EndsWith(","Then Insert_Statement Insert_Statement.Remove(Insert_Statement.Count 11)
 
       Insert_Statement += ")"

 
       '
        OpenConnect()
        Using Cmd As New SqlClient.SqlCommand(Insert_Statement, ConSql)
            For i As Integer = 0 To Table.Count - 1
                Cmd.Parameters.AddWithValue("@" + Table.Keys.ElementAt(i), Table.Values.ElementAt(i))
            Next

            For Each parm As SqlClient.SqlParameter In Cmd.Parameters
                If IsNothing(parm.Value) Or IsDBNull(parm.Value) Then
                    parm.Value = DBNull.Value
                End If
            Next

            Resuilt = Cmd.ExecuteNonQuery

            '
تحصيل رقم السجل
            Cmd
.CommandText "Select @@IDENTITY"
 
           Resuilt CType(Cmd.ExecuteScalar(), Integer)

 
           If Msg True Then
                If Resuilt 
0 Then
                    MessageBox
.Show("تمت الاضافة بنجاح""حفظ التعديلات"MessageBoxButtons.OKMessageBoxIcon.InformationMessageBoxDefaultButton.Button1MessageBoxOptions.RightAlign)
 
               Else
                    MessageBox
.Show("فشلت عملية الاضافة""حفظ التعديلات"MessageBoxButtons.OKMessageBoxIcon.StopMessageBoxDefaultButton.Button1MessageBoxOptions.RightAlign)
 
                   Resuilt 0
                End 
If
 
           End If
 
       End Using
        CloseConnect
()
 
       Return Resuilt

    End 
Function 

شرح الدالة الخاصة بالاضافة 
وسائط الدالة هي 
TableName : اسم الجدول الذي سنتعامل معه
Table As Dictionary : جدول البيانات الذي سنتعامل معه و هو عبارة عن مصفوفه من النوع Dictionary تحتوي على عمودين واحد اخزن فيه اسماء الاعمدة و الثاني اخزن فيه قيمة كل عمود (ستتضح اليتها مع العمل و هي بسيطة جداً)
KeyFiled : اسم حقل المفتاح الرئيسي الخاص بالجدول ليتم استثنائه في عملية الاضافة
Msg : متغير منطقي (بولياني) اتحكم عن طريقه بعرض رسالة الاضافة من عدمها

PHP كود :
       Dim Resuilt As Integer 0
        Dim Insert_Statement 
As String "insert Into " TableName " ("

 
       If Table.ContainsKey(KeyFiledThen
            Table
.Remove(KeyFiled)
 
       End If


 
       Dim Column As String String.Empty
 
       For X As Integer 0 To Table.Count 1
            Column 
Table.Keys.ElementAt(X)
 
           Insert_Statement += Column ","
 
       Next 
انشاء متغير نصي يحمل جملة الاضافة بشكل ديناميكي يقوم بتجميعها وفق الوسائط المرسلة للدالة و من ثم يحذف حقل المفتاح الرئيسي من المصفوفة السابقة الخاصة بالجدول و بعدها يمر على باقي حقول الجدول و يضيفها لجملة الاستعلام

PHP كود :
       If Insert_Statement.EndsWith(","Then Insert_Statement Insert_Statement.Remove(Insert_Statement.Count 11)
 
       Insert_Statement += ")" " Values ("
 
       '
        For X As Integer = 0 To Table.Count - 1
            Column = Table.Keys.ElementAt(X)
            Insert_Statement += "@" & Column + ","
        Next

        If Insert_Statement.EndsWith(",") Then Insert_Statement = Insert_Statement.Remove(Insert_Statement.Count - 1, 1)
        Insert_Statement += ")" 
نزيل الفاصلة اخر جملة الاضافة و بعدها نمر مرة اخرى على حقول المصفوفة لنكون بارميتر لكل حقل و نضيفه لجملة الاضافة
و نزيل بعدها الفاصلة الاخيرة و نكون بذلك قد كونا جملة اضافة لكل الحقول الموجودة في المصفوفة و التي تمثل حقول الجدول 

PHP كود :
       OpenConnect()
 
       Using Cmd As New SqlClient.SqlCommand(Insert_StatementConSql)
 
           For i As Integer 0 To Table.Count 1
                Cmd
.Parameters.AddWithValue("@" Table.Keys.ElementAt(i), Table.Values.ElementAt(i))
 
           Next

            For Each parm 
As SqlClient.SqlParameter In Cmd.Parameters
                If IsNothing
(parm.Value) Or IsDBNull(parm.ValueThen
                    parm
.Value DBNull.Value
                End 
If
 
           Next

            Resuilt 
Cmd.ExecuteNonQuery 
نفتح الاتصال و نعرف كائن Command مع الوسائط المطلوبة 
نضيف بارمترات لكائن الـ Command عبر المرور على عناصر المصفوفة حيث نضيف اسم البارمتر موافق لاسم الحقل و نعطيه القيمة المخزنة في العمود الثاني الخاص بقيمة العمود
بعدها نقوم بالمرور على بارمترات الكائن Command و نسند القيمة Null لكل القيم الفارغة ان وجدت حتى لا نقع في مشاكل الادخالات الفارغة
و اخيراً ننفذ عملية الاضافة

PHP كود :
           'تحصيل رقم السجل
            Cmd.CommandText = "Select @@IDENTITY"
            Resuilt = CType(Cmd.ExecuteScalar(), Integer)

            If Msg = True Then
                If Resuilt > 0 Then
                    MessageBox.Show("تمت الاضافة بنجاح", "حفظ التعديلات", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign)
                Else
                    MessageBox.Show("فشلت عملية الاضافة", "حفظ التعديلات", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign)
                    Resuilt = 0
                End If
            End If
        End Using
        CloseConnect()
        Return Resuilt 
بعد العملية السابقة سنقوم بتحصيل رقم السجل المضاف
و سنفحص قيمة المتغير البولياني و على اساسه نعرض رسالة الاضافة
اخيراً نعود بقيمة السجل المضاف لنستفيد منها و نورثها للابناء

طبعاً كان بامكاننا الاستفادة من الدالة الخاصة بالموضوع السابق و نتحصل على رقم السجل الجديد قبل الاضافة , و لكن ليكون هناك تنوع بالطرق احببت السير بهذا الاتجاه

اتمنى ان تكون الدالة مفهومة و سهلة الادراك


يتبع...
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}


الردود في هذا الموضوع
مثال للتعامل مع الجداول المرتبطة - عن طريق الكلاسات - بواسطة ابو ليلى - 09-04-17, 01:27 AM

المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  ابسط كود لرفع الملفات عن طريق سيرفر FTP Basil Abdallah 2 3,956 20-11-20, 07:21 PM
آخر رد: walihn
  لفهم كيفية الربط الذي يتم بين الجداول viv 4 4,991 03-10-20, 05:34 PM
آخر رد: Arfat007
  العلاقات بين الجداول-الاضافة و الحذف و التعديل-برنامج لحفظ مصادر الموقع ابو ليلى 13 16,911 04-04-19, 10:08 PM
آخر رد: اباذر
  مثال القراءة والكتابه على ملف تيكست Txt على الانترنت + مثال + شرح m.sami.ak 11 8,396 02-06-18, 09:46 PM
آخر رد: YousefOkasha
Exclamation [VB.NET] التعامل مع ال CMD عن طريق ال TextBox YousefOkasha 5 5,001 02-06-18, 09:34 PM
آخر رد: YousefOkasha
  [درس فيديو] مثال بسيط لبرنامج إجازات فقط لأغراض الشرح (الدرس الأول) عبدالله الدوسري 7 11,537 28-04-18, 06:55 PM
آخر رد: moniam
  موضوع الاستاذ رامي مثال \ لطريقة تفعيل برنامجك عند العميل وتغيير كلمة مرور اRamilove سعود 8 7,693 06-10-17, 01:43 AM
آخر رد: حمادة دراز
  الترقيم التلقائي في الجداول مشاكل و حلول ابو ليلى 5 3,809 09-04-17, 01:35 AM
آخر رد: ابو ليلى
  صمم الكلاس الخاص بك - كلاس للتعامل مع SQL SERVER ابو ليلى 11 8,708 03-09-16, 07:43 PM
آخر رد: tryold
  [درس فيديو] تشغيل اوامر Run من البرنامج & مثال غلق الويندوز بعد وقت محدد باستخدام VB.net أحمد النجار 1 3,852 23-12-15, 04:26 AM
آخر رد: الماجيك مسعد

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم