مقدمة إلى لغة الإستعلام المتكاملة LINQ وكيف تستخدمها في مشاريعك

21-10-2013 LINQ
إعلان

كمبرمج تطبيقات أي كان نوعها فغالبا ستحتاج إلى قاعدة بيانات تقوم بحفظ البيانات إسترجاعها تعديلها وحذفها أيضا ضمن متطلبات البرنامج, فعلى سبيل المثال إذا كنت تبرمج نظاما لمكتبة فبالتأكيد أنت بحاجة إلى جدول في قاعدة البيانات تقوم بإضافة بيانات الكتب وتعديلها وحذفها, مثل هذه العمليات أصبحت روتينية حتى في أبسط الأنظمة, العديد من الأساليب أتاحتها مايكروسوفت لمبرمجين الدوت نت من خلال Visual Studio للتعامل مع قواعد البيانات, لم أتطرق إلى معظمها وأكتفيت بإستخدام ADO.NET CommandText فترة لا بأس بها, مع وجود بعض المآخذ عليها إلا أنها كانت تفي بالغرض, لاحقا قامت مايكروسوفت بتطوير و تسهيل الأمور أكثر ليصبح التعامل مع قواعد البيانات متوافق بشكل أكبر مع مفهوم البرمجة الكائنية Object Oriented Programming OOP بعد أن كان الأمر مجرد إستعلامات مباشرة على قاعدة البيانات.

LINQ إختصار لجملة Language Integrated Query وهي عبارة عن مجموعة من الخصائص والمميزات ظهرت بداية في Visual Studio 2008 لتمكنك من كتابة الإستعلامات على قواعد البيانات بوجود مميزات كبيرة وأدوات تجعل منه أكثر سهولة وأقل إحتمالا لوجود الأخطاء.

تعتبر LINQ من أسهل الطرق حاليا في تنفيذ الإستعلامات على قواعد البيانات مثل الإضافة التعديل الحذف والتعامل مع "Relational Database" وغيرها, Visual Studio يحتوي على LINQ Provider assemblies التي تمكنك من إستخدام LINQ من خلال الدوت نت على مستوى SQL Server database,ADO.NET Datasets,Xml documents, أي أن الأمر ليس مقتصرا فقط على قاعدة بيانات MSSQL وجداولها بل يمكنك الإستفادة منها حتى أثناء التعامل ملفات XML.

طورت مايكروسوفت أسلوب جديد وحديث لكتابة الإستعلامات بدل من كتابتها على شكل نصوص غير مستفيده من خاصية Auto Complete الموجودة داخل Visual Studio بأسلوب يحتمل وقوع الكثير من الأخطاء أثناء كتابتها إلى أسلوب متطور بشكل أكبر حيث يمكنك كتابة الإستعلامات من خلال إحدى لغات البرمجة في الدوت نت مثل سي شارب الفيجيوال بيسك مثل أي كود عادي تقوم بكتابتة بدلا من إستخدام جمل SQL التقليدية. لن يكون هناك أية أخطاء إملائية أو غيرها نظرا لأنك تكتب كودات عادية وسيتعرف البرنامج في حال وجود خطأ "Strongly Typed" كما أن خاصية Auto Complete ستستفيد منها بالكامل عند إستخدامك LINQ.

من الجدير بالذكر أن الإستعلامات التي تكتب من خلال LINQ يتم تحويلها لاحقا إلى إستعلامات SQL عادية

لكي تكون الأمور أكثر وضوحا سنقوم بإنشاء مشروع بسيط يحتوي على الأوامر الأساسية في أي نظام يتعامل مع قاعدة بيانات وهي الإستعلام الإضافة التعديل والحذف وسنقوم بتوضيح كيفية تجهيز مشروعك لتقوم بإستخدام LINQ بداخلة من خلال LINQ To SQL

قم بإنشاء قاعدة بيانات LINQFeatures تحتوي على جدول واحد فقط خاص بالمواضيع Posts وقم بإضافة الحقول التالية إلى الجدول :

  • ID : الرقم المتسلسل للموضوع
  • Title : عنوان الموضوع
  • Content : نص الموضوع
  • Date : التاريخ الذي أضيف به الموضوع

داخل مشروع ASP.NET Web Forms جديد نقوم بربط قاعدة البيانات بالمشروع, لفعل ذلك قم بإضافة عنصر LINQ to SQL Classes إلى مشروعك ثم قم بإختيار الإسم المناسب للعنصر, قمت بتحديد الإسم LINQFeaturesDB.

بعد إضافة العنصر إلى المشروع الخاص بك ستحصل على شاشة شبه فارغة تطلب منك إضافة الجداول إليها وهو فعلا ما يقوم بفعلة العنصر الذي قمنا بإضافته مسبقا "LINQFeaturesDB" والذي ينشئ Class خاص بكل جدول تقوم بإضافته إلى الملف من خلال السحب والإفلات "Drag and Drop".

قم بإنشاء إتصال بقاعدة البيانات لنقوم بتصفح الجداول بداخلها, لفعل ذلك قم بالذهاب إلى نافذة Server Explorer, قم بضغط الزر الأيمن على Data Connections واختر Add Connection

ستظهر لك نافذة أخرى تطلب منك تحديد نوع قاعدة البيانات, إذا كانت قاعدة البيانات الخاصة بك موجوده كملف mdf بشكل منفصل قم بإختيار Microsoft SQL Server Database File وإذا كنت تتعامل مع قاعدة البيانات من خلال SQL Server Management Studio فقم بإختيار Microsoft SQL Server

الإسم الإفتراضي لسيرفر قاعدة البيانات SQL Server يمكن التعبير عنه كنقطة "." وبعدها أختر قاعدة البيانات التي قمت بإنشائها مسبقا

بعد الإنتهاء من هذه المرحلة نكون قد أنشأنا الإتصال بقاعدة البيانات, سنقوم الان بإعداد الملف الخاص بجداول قاعدة البيانات LINQFeaturesDB.dbml. حسنا قم بفتح الإتصال واختر الجدول Posts ثم قم بسحبة وإفلاته في المنطقة الفارغة

سيظهر لك بهذا الشكل مع الإنتباه لإسمه الجديد, فقد تم تعديل أسمه من Posts إلى Post وهي إضافة تقوم LINQ بإستخدامها لتأخذ المفرد من الأشياء لكي تتعامل معه لاحقا على أنه مفرد وأن مجموعة المواضيع في الجدول يعبر عنها بقائمة من نوع Post.

الان يمكننا القول أننا انتهينا من مرحلة تجهيز المشروع لإستخدام LINQ في كتابة الإستعلامات على قاعدة البيانات بدل من إستخدام جمل SQL التقليدية القديمة ولكي لا أطيل عليكم الحديث سأقوم بإنشاء إستعلام بسيط يقوم بإرجاع كافة العناوين "Titles" لكافة المواضيع في جدول Posts, ولأن قاعدة البيانات فارغة حاليا قمت بإضافة مجموعة من البيانات العشوائية لتفي بالغرض.

سأقوم بكتابة الإستعلام داخل Page_Load event لكي يتم تنفيذة بمجرد تحميل الصفحة مباشرة ولأننا حاليا نقوم بتوضيح كيفية التعامل مع LINQ بشكل مباشر لا بصدد توضيح الأماكن التي يجب أن يوضع بها كل إستعلام. قبل كل شيئ سنقوم بتعريف كائن Object من الفئة LINQFeaturesDBDataContext لكي تتيح لنا التعامل مع قاعدة البيانات التي قمنا بإنشائها.

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

LINQFeaturesDBDataContext db = new LINQFeaturesDBDataContext();
protected void Page_Load(object sender,EventArgs e)
{
	foreach (Post p in db.Posts)
	{
		Response.Write("<h1>"+p.Title+"</h1>");
	}
}

كما تلاحظ قمنا بإنشاء الكائن db من الفئة LINQFeaturesDBDataConext وبعد ذلك قمنا بعمل جملة الدوران foreach على كافة العناصر الموجوده في جدول Posts من خلال تعريفها بالفئه Post, لاحظ أن db.Posts هي قائمة تحتوي على كافة المعلومات في جدول Posts ويمكن الوصول إليها بشكل مباشر, أما العناصر الموجودة في القائمة فهي من نوع Post. يمكنك الإطلاع على شرح مختص بجملة الدوران foreach.

نتيجة تنفيذ الكود السابق

البحث من خلال LINQ

حسنا ماذا لو أردنا القيام بالبحث من خلال LINQ, من الطبيعي أن أية مجموعة من البيانات أثناء مرحلة معينة تحتاج إلى معيار معين لإرجاع البيانات كما هو في محركات البحث التي تعود عليك بنتائج وفق كلمة البحث التي قمت بكتابتها.

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

قمت بكتابة مثال بسيط يقوم بإرجاع البيانات التي تحتوي الرقم 1 في العنوان من خلال هذا الكود

IQueryable<Post> _post = from p in db.Posts
                               where p.Title.Contains("1")
                               return p;
foreach(Post post in _post)
{
        Response.Write("<h1>" + post.Title + "</h1>");
}

قمنا بتعريف قائمة من الفئه IQueryable والتي تشبه إلى حد كبير List في التعامل معها ولكن هناك بعض الفروقات الجوهرية في الإستخدام يمكنك أن تجدها هنا

أي إستعلام "Select" يتم تنفيذة على قاعدة البيانات يقوم بإرجاع قيم معينة وعلينا إنشاء المتغير الذي سنقوم بتخزين هذه القيم بداخله بناء على نوع البيانات الراجعة, IQueryable هو نوع البيانات الذي تقوم بإرجاعه إستعلامات LINQ بشكل إفتراضي لذلك قمت بإنشاء قائمة من نوع IQuerayble وليس عنصر واحد فقط وذلك لإحتمال رجوع أكثر من نتيجة تنطبق عليها شروط البحث.

ملاحظة : في بعض الأحيان تقوم بالإستعلام عن ID الخاص بموضوع معين وتظن أنه سيعود عليك بصف واحد فقط, فعليا لا يعلم LINQ ذلك بل يفترض أن هناك العديد من الحقول التي تحتوي نفس النتيجة ويرجع لك بقائمة, لحل مثل هذه الإشكاليات قم بإستخدام FirstOrDefault في نهاية الإستعلام.

معيار البحث الذي قمنا بإستخدامة في المثال السابق هو Title.Contains, أي قم بإرجاع كافة المواضيع التي تحتوي عناوينها الرقم 1

بعد أن عدنا بنتيجة الإستعلام الأن يمكننا أن نقوم بتنفيذ جملة foreach عليها لعرض النتائج للمستخدم وستكون نتيجة الإستعلام في الأعلى كما يلي

هنا نفس الكود السابق ولكن ضمن معيار بحث مختلف, StartWith تقوم بإرجاع كافة الصفوف التي يبدأ عنوانها بحرف A.

        IQueryable<Post> _post = from p in db.Posts
                                     where p.Title.StartsWith("A")
                                     return p;

إضافة صف من خلال LINQ

بما أن LINQ قام بتحديد كيفية تعاملنا مع قواعد البيانات والجداول بداخلها على أنها كائنات فإن ذلك يشكل لدينا فكرة مسبقا عن كيفية إضافة صف إلى قاعدة البيانات والذي يكون عبارة عن كائن Object من نوع الجدول الذي نرغب بإضافة الصف فيه.

فلو أردنا إضافة موضوع جديد كيف يتم ذلك ؟ لتوضيح ذلك قمت بإنشاء نموذج بسيط يحتوي على بيانات يتم إدخالها من المستخدم "عنوان الموضوع ونص الموضوع" وعند الضغط على زر إضافة يقوم البرنامج بإضافة صف جديد إلى الجدول يحتوي على المعلومات التي قمنا بإدخالها في النموذج.

الكود الذي قمت بكتابتة داخل زر الإضافة

Post p = new Post();
p.Title = txt_title.Text;
p.Content = txt_content.Text;
p.Date = DateTime.Now.Date;

db.Posts.InsertOnSubmit(p);
db.SubmitChanges();

قمنا بإنشاء كائن من الفئة Post وأسندنا القيم إلى المتغيرات الخاصه به وبعدها قمنا بإدراج الكائن داخل جدول المواضيع "db.Posts.InsertOnSubmit" ثم قمنا بتأكيد الإضافة.

النتائج في قاعدة البيانات

التعديل بإستخدام LINQ

اما التعديل فيتم من خلال إسترجاع الموضوع بواسطة ID الخاص به وبعد ذلك تعديل القيم ومن ثم حفظ التغييرات "SubmitChange"

Post _post = (from p in db.Posts
	     where p.Id.Equals(5)
	     select p).FirstOrDefault();

_post.Title = txt_title.Text;
_post.Content = txt_content.Text;
_post.Date = DateTime.Now.Date;
db.SubmitChanges();
Response.Write("تم تعديل البيانات بنجاح");

النموذج

التعديل

حذف صف بإستخدام LINQ

بالنسبة للحذف يمكنك استخدام الكود التالي

Post _post = (from p in db.Posts
             where p.Id.Equals(5)
             select p).FirstOrDefault();
            
db.Posts.DeleteOnSubmit(_post);
db.SubmitChanges();
Response.Write("تم حذف البيانات بنجاح");

هناك العديد من المميزات الأخرى التي توفر عليك الوقت والجهد في كتابة الإستعلامات وخصوصا على "Relational Databases"

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


عن محمد جمال

مهندس حاسوب ومطور برمجيات, أعمل Freelancer في تطوير تطبيقات الويب من خلال ASP.NET منذ عام 2007 قمت بإنشاء عدة مشاريع في مجالات مختلفة (المتحكمات الدقيقة, الأنظمة المضمنة, الروبوت, برامج سطح المكتب, أنظمة قواعد البيانات) ومن هواياتي الخط العربي

subscribe

إعلان
إعلان
blog comments powered by Disqus

تنويه : الأراء في هذا الموقع شخصية ولا تبت لأحد بصلة تحت أي حال من الأحوال