تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[VB.NET] تطبيق على طرق LINQ - صانع اكواد SQL صغير mini SQL generator
#1
بسم الله الرحمن الرحيم 
السلام عليكم ورحمة الله وبركاته اعضاء المنتدى الكرام

الموضوع بلغة C#

لايخفى عليكم اخواني الكرام اهمية وقوة تقنية LINQ ، فهذه التقنية جعلت التعامل مع البيانات اسهل بكثير جدا ، فما كان يتطلب عديد السطور لانجازة اصبح الان يكفي سطر واحد لعمله


تقديم :

تقنيه LINQ ليست فقط لقواعد البيانات ، في الحقيقة هذه التقنيه تتعامل مع اي فئة تتضمن الواجهة IEnumerable اي قابلة للعد ، وهذا يشمل المصفوفات Arrays و القوائم generic lists

تتضمن هذه الواجهة طرق كثيرة جدا للتعامل مع البيانات ، مثل Select , Where , Aggregate وغيرها الكثير والكثير

لذلك فكرت انه من باب التطبيق نقوم بعمل مثال يقوم بانشاء استعلام SQL بناء على بيانات الجدول المختارة من المستخدم ، او ما يصطلح الاخوة على تسميته "صانع اكواد"

ويجب قبل البدأ ان اخبركم ان الهدف من هذا المثال هو التدرب على استخدام LINQ وليس هو شرح كيفية عمل برنامج صانع اكواد ، فهذا موضوع قد قتل بحثا من جانب الاخوة الكرام

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


مفاهيم اساسية خارج LINQ : 


  1. string interpolation الادخال وسط النصوص : 

    تتيح لنا هذه الميزة ادخال القيم وسط النصوص بطريقة سهلة جدا واكثر امانا ، 
    مثلا اذا كان لدينا متغير اسمه i نريد ان ندخله وسط قيمة نصية فان المطلوب هو ان تسبق القيمة النصية ب العلامة $ وان تضع المتغير داخل قوسين {} :

كود :
Dim str As String = $"I'm {i} years old"

المطلوب :

 قيمة من نوع String تمثل نص الاستعلام بالشكل التالي حسب الصفوف المختارة :

PHP كود :
SELECT [Col1],[Col2],[Col3FROM [TableWHERE [Col1]='Value' AND [Col2]='Value' 


البداية :

نبدأ بتصميم بسيط يؤدي الغرض :

   

لاحظ الداتا جريد فيو قمنا باضافة 4 اعمدة لها عبارة عن : 
  • اسماء الاعمدة ،
  • هل هذا العمود داخل في جملة SELECT ،
  • هل هذا العمود داخل في قيمة WHERE ،
  • اذا كان داخل في جملة WHERE ما القيمة المطلوبة للشرط
الكود : 

دعونا اولا نفكر فيما سنحتاجه ،

صيغة الاستعلام التي نريدها تتكون من كلمات ثابتة : "SELECT" و "FROM" و "WHERE"  

وكلمات مغيرة : اسماء الحقول المختارة بعد SELECT وكذلك الشروط الموضوعة بعد WHERE وكذلك اسم الجدول

طيب لذلك سنقوم بتعريف 4 متغيرات من نوع String 
  • tableName : وهو يمثل اسم الجدول المطلوب انشاء قيمة استعلام له
  • selects : الحقول المطلوبة محاطة ب [] و مفصول بينها ب ,
  • wheres : حقول الشروط محاطة ب [] ايضا ومتبوعة بالقيمة على شكل ='value' و كذلك مفصول بينها ب AND
  • sqlCommand : نخزن فيه الاستعلام المنشأ

هيا بنا في حدث btnGenerateSql.Click نعرف متغير اسم الجدول ونسند له قيمة من مربع النص الخاص باسم الجدول محاط بالاقواس [] :


كود :
       Dim tableName As String = $"[{txtTableName.Text}]"


كيف نحصل على القيمة المطلوبة للمتغير selects ؟

طيب نبدأ العمل الحقيقي الان ، نريد الحصول على صفوف الداتا جريد فيو على شكل IEnumerable من نوع DataGridViewRow لنتمكن من استخدام طرق LINQ عليها ،

لفعل ذلك نستخدم الطريقة Cast ونمرر لها النوع DataGridViewRow :


كود :
       Dim selects = dgvTable.Rows.
           Cast(Of DataGridViewRow)()


جميل جدا ، الان ركزو معي جيدا ، نريد اختيار الصفوف المختارة فقط كجزء من Select ، اي الصفوف التي فيها قيمة الخلية الثانية ب True ، 

لفعل ذلك نحن بحاجة الى الطريقة Where ، التي هي دالة الاختيار ، وظيفتها انها تختار من عناصر بيانات العناصر التي توافق شرط معين ، تقبل مدخل تعبير لمدا يمثل الشرط الذي يتم الاخيار بناء عليه ، وهو في هذه الحالة قيمة الخلية الثانية من الصف الحالي x.Cells(1).Value 


   

كود :
       Dim selects = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(1).Value)


الان حصلنا على الصفوف المطلوبة فقط ، جميل جدا نريد الان الحصول منها على اسماء الاعمدة المطلوبة ( قيمة الخلية الاولى في الصف ) محاطة ب [] ،

لفعل ذلك نستخدم الدالة Select التي تسمي دالة التحويل ، وظيفتها انها تحول كل العناصر التي تطبق عليها الى صورة اخرى ، في حالتنا نريد تحويل عناصر صفوف الداتا جريد فيو DataGridViewRow الى قيم نصية String تمثل اسماء الاعمدة ، الدالة تقبل مدخل تعبير لمدا يمثل التحويل المطلوب على كل عنصر ، وهو في هذه الحالة قيمة الخلية الاولى محاطة باقواس $"[{x.Cells(0).Value}]"


   

كود :
       Dim selects = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(1).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]")


طيب جميل جدا الان ماذا اذا لم يختار المستخدم اي صف ؟ في هذه الحالة تكون القائمة فارغة ، نريد في هذه الحالة ان تكون القيمة الافتراضية "*" هي العنصر الوحيد ، يعني في حالة لم يتم اختيار صف معين نحن سنعيد القيمة * التي تعني كل الاعمدة في SQL  ، 

لفعل ذلك نستخدم الدالة  DefaultIfEmpty التي وظيفتها انها ترجع بعنصر وحيد عبارة عن القيمة الافتراضية التي تمررها لها في حالة كانت القائمة التي تطبق عليها فارغة ، في هذه الحالة نمرر لها القيمة "*"


كود :
       Dim selects = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(1).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]").
           DefaultIfEmpty("*")


طيب الان جميل جدا جدا جدا ، معنا قائمة فيها كل اسماء الاعمدة المختارة ، محاطة باقواس [] وفي حالة لم تيم اختيار شيء معنا * ،

الخطوة القادمة هي تجميع عناصر هذه القائمة في قيمة نصية واحدة مفصول بينهم ب ,

لفعل ذلك نستخدم الدالة Aggregate التي وظيفتها تجميع عناصر القائمة في قيمة واحدة ، تأخد مدخل تعبير لمدا ذو مدخلين ومخرج واحد

يطلب منك اذا كان لديك هذين العنصرين (x,y) مثلا كيف تقوم بتجميعهم ؟ 

نخبره اننا نريده ان يضع القيمة الاولى متبوعة بفاصلة متبوعة بالقيمة الثانية 

كود :
Function(x, y) $"{x},{y}"


كود :
       Dim selects = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(1).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]").
           DefaultIfEmpty("*").
           Aggregate(Function(x, y) $"{x},{y}")


حسنا الان انتهينا من المطلوب للمتغير selects ، الان وقت مناسب جدا لاخذ كوب ساخن من الشاي الثقيل عديم السكر  Big Grin 

انتهيت ؟ مرحبا بك مجددا  Smile 

بقي لنا ان نحصل على قيمة المتغير wheres 

نبدأ مثلما بدأنا سابقا ، نحول العناصر باستخدام Cast :


كود :
Dim wheres = dgvTable.Rows.
           Cast(Of DataGridViewRow)()


نختار الصفوف المحددة فقط في الخلايا الثالثة ( CheckBox الخاص ب Where ) 

كود :
       Dim wheres = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(2).Value)



   

بعد ذلك نحصل على قيم الصفوف المطلوب عمل شرط بها وكذلك احاطتها باقواس [] واضافة قيمة الشرط لها ='value'
الكود التالي نخبره ان يحول كل عنصر من القائمة الى ما نريده :


كود :
       Dim wheres = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(2).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]='{x.Cells(3).Value}'")


لاحظ ان x.Cells(0).Value تمثل اسم العمود بينما x.Cells(3).Value تمثل قيمة الشرط بعد Where=


   
   

نجعل القيمة الافتراضية 1=1 ، في حالة ليس هناك عناصر شرط نريد جلب الكل في الاستعلام :

كود :
       Dim wheres = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(2).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]='{x.Cells(3).Value}'").
           DefaultIfEmpty("1=1")


واخيرا تجميع العناصر والفصل بينهم  ب AND

كود :
       Dim wheres = dgvTable.Rows.
           Cast(Of DataGridViewRow)().
           Where(Function(x) x.Cells(2).Value).
           Select(Function(x) $"[{x.Cells(0).Value}]='{x.Cells(3).Value}'").
           DefaultIfEmpty("1=1").
           Aggregate(Function(x, y) $"{x} AND {y}")


اخر خطوة هي وضع العناصر في متغير الاستعلام :

كود :
        Dim sqlCommand As String = $"SELECT {selects} FROM {tableName} WHERE {wheres}"

وبعد ذلك اخراجها للمستخدم : 

كود :
        txtSql.Text = sqlCommand

حسنا انتهينا فعلا ،

النتيجة :


   

مع عدم اختيار اي شيء :


   

اتمنى اكون قد وفقني الله لتبسيط المعلومة ، انا جاهز للاسئلة بخصوص هذا الموضوع
اتمنى ان ينتشر استخدام LINQ بين الاخوة العرب


الملفات المرفقة
.zip   MiniSqlGeneratorVB.zip (الحجم : 55.66 ك ب / التحميلات : 19)
الرد
#2
متابع معكم استاذ
رغم انني لم استخدم قبلا قواعد البيانات و لا احسنها
املا في ان اتعلم منكم سيدي
 لعل الكلمة التي تنفعني لم أكتبها بعد
عبد الله بن المبارك
الرد
تم الشكر بواسطة: Anas Mahmoud , حريف برمجة , Hasaneen
#3
(07-09-20, 02:09 PM)عبد الهادي بهاب كتب : متابع معكم استاذ
رغم انني لم استخدم قبلا قواعد البيانات و لا احسنها
املا في ان اتعلم منكم سيدي

اهلا بك اخي عبد الهادي

للتوضيح فقط لست بصدد شرح قواعد بيانات هنا بل كنت اطبق على LINQ ، التقنية التي تتعامل مع القوائم والمصفوفات Arrays بانواعها 

كود :
       Dim Numbers As Integer() = {6, 8, 12, 22, 30, 43, 55, 68, 88, 99}
       Dim NumbersGreaterThan10 = Numbers.Where(Function(x) x > 20).ToArray

       MsgBox(Numbers.
              Select(Function(x) x.ToString).
              Aggregate(Function(x, y) $"{x},{y}"))


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

https://www.youtube.com/watch?v=xAON76xP...W82B6d4irC
الرد
تم الشكر بواسطة: حريف برمجة , Hasaneen


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  تصميم برنامج صانع الشهادات التقديرية عبد الهادي بهاب 0 103 05-09-20, 06:17 PM
آخر رد: عبد الهادي بهاب
  [مشروع] تصميم تطبيق بسيط لسورة البروج ( التزامن بين الصوت و النص ) عبد الهادي بهاب 0 78 03-09-20, 03:06 AM
آخر رد: عبد الهادي بهاب
  برنامج صانع الاكواد الاصدار المجاني الجديد aljzazy 12 1,497 01-09-20, 03:50 AM
آخر رد: نورالدين32
  ممكن Generator code abarrak 3 299 03-08-20, 01:31 AM
آخر رد: حريف برمجة
Lightbulb سورس كود برنامج صانع الاكواد asemshahen5 53 19,540 02-08-20, 09:33 AM
آخر رد: manu
  مشروع صغير لطباعة ملصقات الباركود وقرائتها بسهولة تامة عابر سبيل 13 20,624 12-05-20, 01:41 PM
آخر رد: mlahcine
  اكواد rawan.alqarni 0 278 22-03-20, 08:58 PM
آخر رد: rawan.alqarni
  [مشروع] تصميم تطبيق لقفل واخفاء الملفات مع السورس كود ahmadpal 10 1,513 18-10-19, 10:43 PM
آخر رد: ahmadpal
Big Grin [مشروع] تطبيق صورة متحركة تتبع مؤشر الماوس مع السورس كود ahmadpal 0 540 14-06-19, 01:22 AM
آخر رد: ahmadpal
Big Grin [مشروع] تصميم محرر اكواد بسيط من خلال الفيجوال بيسك مع السورس كود ahmadpal 0 576 08-06-19, 03:56 AM
آخر رد: ahmadpal

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


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