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

الدليل العملي لاستخدام Linq To Sql مع قواعد بيانات Sql Server Ce

بدأه مهند عبدالحفيظ في 3 فبراير 2009 · 11 رد · 8,870 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه

سأبدأ من الألف إلى الياء وذلك للمبتدئين في استخدام LINQ

خطوات عمل البرنامج :

  1. انشاء برنامج جديد فارغ من نوع Windows Form Application .
  2. إضافة و تصميم قاعدة البيانات عن طريق Server Explorer .
  3. انشاء فئات العمل ل LINQ عن طريق SQLMetal
  4. تطبيق استعلامات LINQ للتعامل مع الباينات ( عرض-حذف-اضافة-تعديل)

طبعا الخطوة الأولى سهلة ولا تحتاج لشرح ... وبعد انشاء البرنامج سيظهر لك نموذج وحيد Form1 اتركه كماهو ونبدأ بالخطوة الثانية ....

بناء وتصميم قاعدة البيانات

لانشاء قاعدة بيانات جديدة : نذهب للقائمة Project ونختار Add New Item و ثم نختار Local DataBase ونسميها اي اسم .فيظهر معالج الاتصال بقاعدة البيانات اضغط Cancel لأننا لا نريد انشاء DataSet .سنجد ملف الداتا قد اضيف لنافذة Solution Explorer نضغط عليه فيفتح لنا ServerExplorer ثم نضيف الجداول لقاعدة البيانات وننشيء العلاقات الازمة .

إضافة قاعدة بيانات موجودة : وللسهولة ساستخدم قاعدة بيانات NorthWind.sdf الشهيرة حيث نختار من قائمة Project ثم Add Existing Item ثم تضيف ملف NorthWind.sdf التي تجدها في المجلد :

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Samples

وسيظهر معالج الاتصال بقاعدة الباينات فنضغط Cancel .

الان هذه الخطوة مهمة لكل قواعد البيانات المحلية : حيث أن الفيجوال ينشيء قاعدتي بيانات احدهما في مجلد البرنامج والثانية للتنفيذ في مجلد Debug وبالتالي فعندما نقوم باضافة بيانات اثناء تنفيذ البرنامج نتفاجأ انها اختفت عندما نستعرض البيانات في server explorer لذلك نقوم بالتالي : من نافذة المشروع Solution Explorer اختار ملف قاعدة البيانات وفي الخصائص عدل الخاصية Copy to Output Directory إلى Do not Copy .

الان نحفظ المشروع تمهيدا للخطوة الثالثة

انشاء فئات العمل مع LINQ

ما هي فئات العمل مع LINQ ؟

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

ان البيئة المثالية لانشاء فئات العمل هي O/R Designer ولكن لا اعلم لماذا لم تضف ماايكروسوفت دعم قواعد بيانات SQL Server CE له!!؟ وبالتالي سنستخدم البرنامج البديل وهو SQLMetal.exe وهو يأتي مع الفيجوال :

  1. اولا نغلق البرنامج ونذهب للمجلد C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
  2. ثم ننسخ الملف SQLMetal.exe إلى مجلد البرنامج الذي فيه ملف Northwind.sdf .
  3. نبقى في مجلد برنامجنا وننشئ اختصار جديد لملف SQLMetal.exe الذي نسخناه
  4. نفتح خصائص الاختصار الذي انشأناه وفي خانة Target (الهدف) نضع بعد اسم البرنامج الاوامر التالية :
     /namespace:NorthWind /code:NorthWind.vb /Language:vb /pluralize NorthWind.sdf


  5. للتوضيح أكثر تصبح خانة الهدف كالتالي :
    "C:\Users\Muhannad\Documents\Visual Studio 2008\Projects\SampleLINQ\SampleLINQ\SqlMetal.exe" /namespace:NorthWind /code:NorthWind.vb /Language:vb /pluralize NorthWind.sdf


  6. والان نقوم بتشغيل ملف الاختصار ستظهر نافذة موجه الاوامر للحظات ثم تختفي وسنجد أنه لدينا ملف جديد في المجلد اسمه NorthWind.vb وهو المطلوب .
  7. نفتح مشروعنا ونختار من قائمة Project اضافة الملف Add existing Item و نذهب لمجلد البرنامج ونضيف ملفنا الجديد NorthWind.VB .
  8. بقي خطوة أخيرة حيث يتطلب اضافة refrence للبرنامج ل System.Data.Linq ..الطريقة لم لا يعرف من قائمة Project ثم Add refrence ثم تحت علامة .NET ستجد System.Data.Linq أضفها للمشروع .

ملاحظة هامة : يجب اعادة انشاء ملف تالفئات عند أي تغيير في تصميم قاعدة البيانات مثلا اضافة جدول جديد أو أعمدة جديدة لجدول موجود وعندها لاتحتاج الا لتشغيل الاختصار السابق وانتبه أن لاتكون قاعدة البيانات مفتوحة في مكان اخر كالفيجوال مثلا .

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

مع التحية

تم تعديل هذه المشاركة بواسطة مهند عبدالحفيظ في 3 فبراير 2009 في 10:24

#2

السلام عليكــم ورحمـة الله وبركاتــه

في الموضوع السابق انشأنا برنامجا يرتبط بقاعدة بيانات NorthWind.sdf أنشأنا فئات عمل Linq باستخدام SQLMetal

ولمن يريد الاستفادة من الدرس يفضل انشاء البرنامج حسب الدرس السابق لأنني سأمزج بين المعلومات النظرية والتطبيق العملي مباشرة في كافة المراحل .

الان ساتطرق للموضوع المهم وهو التعامل مع LINQ بعد انتهينا من بناء الفئات باستخدام SQLMetal .

ان الفئات التي تشكلت لدينا هي صلتنا بقاعدة البيانات فبعد الان اصبح كل سجل بقاعدة اليينات ممثل بكائن وكل مجموعة سجلات ممثلة ب List - أو بنية تشبهها بالاحرى - مثلا الجدول Customers الان نصل اليه عن طريق الكائن Customers والذي يحتوي على كائنات من نوع Customer التي انشأها لنا SQLMetal وستجد لكل فئة من نوع Customer خصائص هي عبارة عن أعمدة الجدول Customer وعند الشرح العملي ستتضح الصورة أكثر .

الان في البرنامج ضع اداة DataGridView على كامل الفورم حيث سنستخدمها لعرض نواتج تجاربنا مع استعلامات Linq .

الخطوة الأولى لاستخدام LINQ TO SQL هو انشاء الكائن DataContext والذي مهمته تأمين الاتصال بقاعدة البيانات وطبعا نحن لن ننشئ هذا الكائن مباشرة انما هناك الفئة Northwind التي انشأها لنا SQLMetal والتي هي اصلا مشتقة من DataContext وبالتالي سننشئ كائن من هذه الفئة كمتغير محلي Field في الفورم . تحت كلمة Public Class .

Public Class Form1

Dim MyDB As New NorthWind.NorthWind"(Northwind.sdf)"

طبعا تلاحظ انا كتبنا NorthWind.NorthWind وذلك لأننا عند انشاء الفئات sqlmetal طلبنا منه أن ينشئ نطاق للأسماء namespace باسم NorthWind فلابد للوصول لفئاتنا استخدام هذا النطاق قبلها .

الان اصبحت كل البيانات في متناول يدك وسنبدأ بتجربة اكواد مختلفة لنتعرف على استعلامات LINQ أكثر ونقول وداعا ل استعلامات SQL وكود ADO.Net الممل والمكرر .

استعلامات LINQ

بشكل عام استعلامات LINQ اما تبدأ ب From وتعيد مجموعة سجلات أو ب Aggregate وتعيد عندها قيمة واحدة وساقوم بترجمة كل استعلام نستخدمه لاستعلام SQL المقابل له ليسهل فهمه .

اولا: استعلامات From :

صيغتها العامة المبسطة

From element In collection [Where condition] Select elements[vars]

وفي مثالنا تصبح Collection تصبح MyDB التي تمثل قاعدة البينات كاملة وطبعا ما بين اقواس مربعة هو اختياري .

الان سنضع جملة from بسيطة في الحدث Form_Load لتعرض البيانات في DataGridView .

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

MyDB.Log = Console.Out

Dim mySource = From cust In MyDB.Customers Select cust

DataGridView1.DataSource = mySource

End Sub

نفذ البرنامج وسترى الجدول Customers كاملا لديك . ولقد اضفت العبارة MyDB.Log = Console.Out حيث ستكتب لك في نافذة Output ما يتم ارساله لقاعدة البينات وسترى انها استعلامات SQL المعروفة فهذه هي وظيفة LINQ to SQL ترجمة ما نكتبه لقاعدة البيانات ولاتنسى ان تلقي نظرة على نافذة Outputبعد كل استعلام .

أعود للاستعلام السابق بامكانك اعتبار cust سجل ,,فترجمته لعبارة مفهومة هو "لكل سجل نفترض ان اسمه cust في مجموعة السجلات MyDB.Customers اعطني cust " يعني كل السجلات ومقابله ب SQL

SELECT * FROM Customers

اما ناتج الاستعلام mySource فهو نوع مجهول Annonymous Type ولاتشغل بالك كثيرا به فالتطبيقات البسيطة ل LINQ لاتحتاج لمعرفة قوية بهذه الانواع .يمكنك اعتبار الناتج مجموعة تحتوي كائنات من نوع Customer.

وناتج الاستعلام يمكنك الاستفادة منه بعدة طرق مثلا في المثال السابق استخدمناه ك Data Source . أو يمكنك التنقل خلاله من خلال حلقة For..Each مثال :

For Each mycust In mySource

Console.WriteLine(mycust.ContactName)

Next

أو اخذ اول سجل منه فقط واستعراض بيناته مثلا ...

Dim FirstCust = mySource.First

Console.WriteLine(FirstCust.CompanyName, FirstCust.ContactName, FirstCust.City, FirstCust.Address)

وكل ما ينطبق على List(of T) ينطبق عليه .. وفوق ذلك يمكن الاستعلام عنه في جملة From جديدة ..مثلا

Dim LondonCust = From x In mySource Where x.City = "London" Select x

وبامكانك ان تضع ناتج الاستعلام LondonCust كمصدر DataSource للداتا جريد .

لاحظ اثناء كتابتك للاستعلامات السابقة أن Visual Basic يقترح عليك العناصر و الحقول ويصحح لك الأخطاء وهذا سبب قولي أن استخدام استعلامات LINQ اسهل واصح من استخدام استعلامات SQL فلامجال مع Linq لخطأ لاتعرف ما هيته ترسله لك قاعدة البينات وتحتار في امره .ويكون سببه بسيط كاختيارك لنوع بيانات خاطئ مثلا String بدلا من Integer فهنا المحرر سيخبرك بالخطا مباشرة.

نعود لبعض التطبيقات وساسرد هنا استعلام LINQ وقم انت باستبداله في حدث Form_Load وشاهد النتيجة وبعده ساذكر استعلام SQL المقابل ولسهولة فهم الاستعلامات ساكتب كل بداية كلمة في سطر.

Dim mySource = From cust In MyDB.Customers _

Select cust.ContactName, cust.City

SQL : SELECT ContactName,City FROM Customers

Dim mySource = From cust In MyDB.Customers _

Select cust.ContactName, cust.City

SQL : SELECT ContactName,City FROM Customers

Dim mySource = From cust In MyDB.Customers _

Where cust.City = "London"

Select cust.ContactName, cust.ContactTitle, cust.Address

SQL : SELECT ContactName, ContactTitle, Address FROM Custemers WHERE City='London'

Dim mySource = From ord In MyDB.Orders _

Where ord.Customer.City = "London" _

Select ord.OrderDate, ord.OrderID, ord.Customer.ContactTitle

SQL : SELECT Orders.[Order Date] , Orders.[Order ID] , Customers.[Contact Title] FROM Orders

INNER JOIN Customers ON Customers.[Customer ID] = Orders.[Customer ID]

WHERE Customers.City = 'London'

لاحظ الاستعلام الاخير أن العلاقات ممثلة بشكل مجموعة كائنات فكل كائن Order يحتوي على كائن Customer يمثل العلاقة بين Customer ID في الجدولين وهذه طريقة ذكية وسهلة لتمثيل العلاقات خاصة العلاقات المتشابكة بين عدة جداول حيث كنت سابقا اكتب اكثر من جملة Inner Join في الاستعلام . وطبعا يمكنك استخدام الكلمات المحجوزة التالية مع الاستعلامات Distinct ,Order By ,Like واقترح عليك ان تجرب ما يقترحه عليك المحرر وتحاول بناء جمل استعلاماتLINQ اكثر تعقيدا لتعتاد على استخدامها . الى لقاء قريب .حيث ساتطرق ل Aggregate و استعلامات اكثر تعقيدا .

تم تعديل هذه المشاركة بواسطة مهند عبدالحفيظ في 12 فبراير 2009 في 10:01

#3

أرجو من أحد المشرفين أن يقوم مشكورا بتنسيق الاكواد بشكل واضح لأني كتبتها بشكل منسق ولا أدري لماذا المحرر لم يعجبه تنسيقي .....مع الشكر

تم تعديل هذه المشاركة بواسطة مهند عبدالحفيظ في 12 فبراير 2009 في 10:04

#4

عفوا للتكرار

تم تعديل هذه المشاركة بواسطة مهند عبدالحفيظ في 12 فبراير 2009 في 09:45

#5

السلام عليكــم ورحمـة الله وبركاتــه

حسب التجربة عليك أن تضع الأكواد في المفكرة أولاً لتتخلص من تنسيقها ثم تنسخها من المفكرة إلى محرر المشاركات هنا فتظهر بشكل سليم.. أما إن نسختها بتنسيقها ثم وضعتها هنا فوراً فستظهر مشاكل..

والله أعلم

قال صلى الله عليه وسلم: من قال إذا أصبح: رضيت بالله ربا وبالإسلام دينا وبمحمد نبيا فأنا الزعيم لآخذن بيده حتى أدخله الجنة. الصحيحة/2686

#6

السلام عليكــم ورحمـة الله وبركاتــه

فشلت جهودي في تنسيق الموضوع السابق ... ولهذا فقد وضعت الموضوعين الأول والثاني بشكل ملفات PDF لمن يريد قرائتهما بشكل واضح .... أرجو أن يكون الموضوع مفيدا نوعا ما ..لأني لا اجد تعليقات او نقاشات او حتى انتقادات ....مع وجود اكثر من 200 قراءة ... فاذا كان هناك غموض اخبروني ..

مع التحية والشكر لجميع الاعضاء والمشرفين.

الموضوع الأول LINQ1.pdf

الموضوع الثاني LINQ2.pdf

#7

جزاك الله كل خير

#8

بارك الله فيك على الشرح المفيد والغني بالافكار الهامة جداً

#9

السلام عليكم

اليوم سنكمل مشوارنا مع استعلامات LINQ ولن ادخل بكل تفاصيل الكلمات المحجوزة للاستعلامات

وقد أضفت البرنامج الذي تم انشاءه في الدرس الأول بشكل رابط لمن يريد اختصار الوقت والتطبيق مباشرة : SampleLINQ.rar.

ثانيا : استعلامات Aggregate

تتميز بانها تعيد قيمة واحدة لأحد دوال التجميع Aggregation

Sum مجموع القيم – Average المعدل الحسابي – Count عدد القيم – Min أصغر قيمة – Max أكبر قيمة .

وهي سهلة الاستخدام

مثال أضف الكود التالي لبرنامجنا في أي مكان تريد ...

Dim CustomerCount = Aggregate cust In MyDB.Customers Into Count()

'SQL : SELECT Count(*) From Customers

Dim OrderSum = Aggregate ord In MyDB.Orders Into Max(ord.OrderDate)

'SQL : SELECT Max([Order Date]) FROm Orders

Console.WriteLine("Custuomers Count: {0} Type : {1} ", CustomerCount, TypeName(CustomerCount))

Console.WriteLine("Max Order Date Count: {0} Type : {1} ", OrderSum, TypeName(OrderSum))

وقد اضفت جملة SQL الموافقة بعد الاستعلام وكما تلاحظ فإن استعلامات Aggregate تعيد قيمة واحدة دائما ونوع متغير ناتج الاستعلام سيكون أحد انواع DataType وليس مجموعة Collection كما اعتدنا .كما يمكن ان يحتوي استعلام From على تجميع باستخدام Aggregate

العلاقات في LINQ TO SQL :

طبعا جميعنا يعرف العلاقات وفائدتها . ومع استخدام Linq اصبح لدينا تطبيق سهل ووصول جيد لكافة كائنات قاعدة البيانات ... وكما سبق فإننا نستخدم قاعدة بيانات NorthWind ولذلك قبل الخوض في علاقاتها هذه صورة توضح بنية العلاقات فيها

post-976-1235170554_thumb.jpg

طبعا كما ذكرت انشاء العلاقات وحفظها في قاعدة البيانات قبل انشاء الفئات باستخدام sqlMetal يسهل بناء استعلاماتنا بشكل كبير حيث يقوم باني الفئات (sqlmetal أو O/R designer ) بتضيمن العلاقات وتقديمها لنا بطريقة برمجية ككائنات . مثلا من الشكل السابق لنفرض أنني اريد معرفة فقط اسماء وارقام المنتجات التي شحنت الى ايطاليا . سيكون عندها استعلام LINQ بهذه البساطة :

From det In MyDB.OrderDetails _

Where det.Order.ShipCountry = "Italy" _

Select det.Product.ProductID, det.Product.ProductName Distinct

هذا في حالة ترجمة العلاقات في الفئات . أما اذا لم يتم انشاء العلاقة في قاعدة البيانات فانت بحاجة ل Join ويصبح الاستعلام نفسه كالتالي :

From det In MyDB.OrderDetails _

Join ord In MyDB.Orders On ord.OrderID Equals det.OrderID _

Join prd In MyDB.Products On prd.ProductID Equals det.ProductID _

Where ord.ShipCountry = "Italy" _

Select prd.ProductID, prd.ProductName Distinct

وطبعا نظير الاستعلامين السابقين في SQL هو :

SELECT DISTINCT Products.[Product Name] FROM [Order Details]

INNER JOIN Orders ON [Order Details].[Order ID] = Orders.[Order ID]

INNER JOIN Products ON [Order Details].[Product ID] = Products.[Product ID] WHERE (Orders.[Ship Country] = 'Italy'

والنتيجة أن علاقة واحد إلى كل أو ما تسمى Foreign Key حيث يكون هناك جدول مفتاح اساسي (Primary-Key ) مثل جدول Customers و جدول اخر يحتوي المفتاح الفرعي (Foreign-Key ) الذي يشير للمفتاح الاساسي تكون ممثلة في فئات Linq to SQL بشكل :

(كل كائن من جدول Primary-Key له مجموعة من كائنات جدول Foreign-Key )

والعكس غير صحيح

(كل كائن من جدول Foreign-Key ممثل بكائن وحيد من جدول Primary-Key )

وهذه الجمل صحيحة مهما تشعبت العلاقات كما شاهدنا بالمثال السابق.

وهذه الميزة لها عيوب عند التعامل مع كمية كبيرة من البيانات حيث سيتم تحميل الجدول المطلوب مع علاقاته والكائنات الفرعية مما يشكل حملا على الذاكرة والمعالج وهذا يمكن التحكم به من خلال Load Options للكائن DataContext كما سنرى لاحقا .

الاستخدامات الاساسية للاستعلامات :

بناء مصدر بيانات Data Source :

كما رأينا سابقا في المقال الثاني يمكن استخدام أي استعلام Linq كمصدر بيانات لأي عنصر تحكم لعرض البيانات وهناك ملاحظة مهمة بالنسبة لاستعلامات Linq وهي أن أي مجموعة استعلامات تعيد نفس القيمة أو السجل أو نفس مجموعة السجلات تؤشر لنفس الكائن حتى لو كانا استعلامين مختلفين . فقد تتفاجأ عند وضع مصدر بيانات ل combobox و DataGrid من نفس الجدول أنه عند تحريك الاختيار في الكومبو تتحرك المؤشرات في datagrid.

التجميع Grouping :

باستخدام Group By حيث يتم فرز السجلات على شكل مجموعات مستقلة وفقا لمعيار معين .لنفرض أنني لا أريد عرض جدول Products بالكامل وانما اريده بطريقة منسقة ومجمعة حسب Category عندها نلجأ ل group By

From pro In MyDB.Products _

Group pro By pro.CategoryID Into CatGroup = Group

هنا يصبح ناتج الاستعلام عبارة عن مجموعتين بشكل شجري بالتالي نحن بحاجة لحلقتين For Each للتجوال عبر جميع السجلات الحلقة الأولى الأولى تعيد مجموعة CatGroup والحلقة الثانية تتجول في هذه المجموعة كالتالي :

Dim mySource = From pro In MyDB.Products _

Group pro By pro.CategoryID Into CatGroup = Group

For Each grp In mySource

Console.WriteLine("Category ID = {0}", grp.CategoryID)

For Each prod In grp.CatGroup

Console.WriteLine("Product Name: " & prod.ProductName)

Next

Next

والاستخدام الاخر الأكثر شيوعا للتجميع هو مع الدوال التجميعية مثلا اذا اردنا أن نجد عدد الطلبيات orders لكل موظف Employee سنستخدم الاستعلام التالي :

From ord In MyDB.Orders _

Group ord By ord.EmployeeID Into EmpGroup = Group _

Select EmployeeID, OrdersCount = EmpGroup.Count()

الترتيب :

باستخدام Order By ويمكن استخدام Take و Skip معها لتعطينا جزء من المجموعة مثلا للحصول على اخر 10 طلبيات نستخدم الاستعلام :

From ord In MyDB.Orders _

Select ord Order By ord.OrderDate Descending _

Take 10

تصفية السجلات :

وهو باستخدام الكلمة Where وبعدها قيمة منطقية و90% من القيم المنطقية والدوال مقبولة بالنسبة Linq to SQL ولاحقا سأعطي أمثلة للدوال واستخدامها بطريقة سهلة مع Linq .

ونصيحتي لكل متعلم جديد ل LINQ جرب ثم جرب ثم جرب كل صيغ الاستعلامات الممكنة .لكي تأخذ مرونة في التعامل ....

وإلى اللقاء مع المقال القادم الذي سيكون عن تعديل البيانات واضافة وحذف البيانات مع Linq .

والسلام ....

المقال كاملا بصيغة PDF LINQ3b.pdf

تم تعديل هذه المشاركة بواسطة مهند عبدالحفيظ في 21 فبراير 2009 في 02:06

1
#10

تعديل وتحديث البيانات

السلام عليكم

كمدخل لمفاهيم تعديل وتحديث البيانات أحب أن اذكر الجميع بأننا في Linq أصبحنا نتعامل مع كائنات وبالتالي مفهوم تحديث البيانات هو عبارة عن تعديل لخصائص هذه الكائنات والمجموعات أو حذف أو اضافة كائنات ثم يقوم مزود Linq to SQL بتحويل تعديلاتنا إلى جمل SQL يتم ارسالها لقاعدة البيانات .

أولا إضافة البيانات :

1- إضافة البيانات لجدول واحد :

نقوم أولا بانشاء نسخة من كائن الجدول ( مثلا Customer أو Category ) ثم نسند القيم للحقول المطلوبة ونستخدم الكائن DataContext لإلحاق البيانات بقاعدة البيانات والميزة الجميلة أن LINQ يقوم لوحده بتحديث بقية الحقول التي لم ندخلها لقيمها الجديدة. مثلا الكود التالي يضيف بيانات لجدول الفئات Categories فيNorthWind ثم يعرض قيمة ID للفئة الجديد .

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As 
System.EventArgs) Handles Button2.Click 
Dim MyDB As New NorthWind.NorthWind("Northwind.sdf") 
MyDB.Log = Console.Out 
Dim myCat As New NorthWind.Category 
With myCat 
.CategoryName = "Arabicaa" 
.Description = "Arabs" 
End With 
MyDB.Categories.InsertOnSubmit(myCat) 
MyDB.SubmitChanges() 
MsgBox("new ID : " & myCat.CategoryID) 

End Sub

لاتنسى أن تلقي نظرة على نافذة Output .

2-إضافة البيانات لجداول مترابطة Master/Details:

غالبا ما نحتاج ادخال المستخدم لإضافة البيانات لعدة جداول مرتبطة مثلا عند ادخال العميل لفاتورة ما نحتاج لإدخال البيانات في جدول الفواتير ثم نضيف تقاصيل كل فاتورة في جدول التفاصيل ... وفي قاعدة Northwind لنفرض أننا نريد إدخال منتجات Products جديدة تتبع لفئة جديدة ..ما سنقوم به هو انشاء كائن جديد من نوع Category وسنجد في خصائصه تلقائيا مجموعة Products فنضيف لها ما نحتاجه من منتجات و نرسل التغييرات لقاعدة البيانات .وهذا مثال الكود :

Dim myCat As New NorthWind.Category 
With myCat 
.CategoryName = "Arabicooo" 
.Description = "Arabians" 
.Products.Add(New NorthWind.Product With _ 
{.ProductName = "AAAAAA",.Discontinued = False}) 
.Products.Add(New NorthWind.Product With _ 
{.ProductName = "BBBBBB",.Discontinued = False}) 
.Products.Add(New NorthWind.Product With _ 
{.ProductName = "CCCCCC",.Discontinued = False}) 
End With 

MyDB.Categories.InsertOnSubmit(myCat) 

MyDB.SubmitChanges() 
MsgBox("CategoryID ID : " & myCat.CategoryID & " My Products : " & _ 
myCat.Products.Count)

ولاحظ أننا لم نضع CategoryID في كودنا لأن Linq to SQL سيتكفل باحضارها . واذا القيت نظرة على نافذة Output ستجد أن كودنا السابق تمت ترجمته لخمسة جمل SQL الأولى لإضافة فئة جديدة Category والثاني للحصول على CategoryID للفئة الجديدة و الثلاث البقية لإضافة المنتجات Product الجديدة .

ثانيا تعديل البيانات :

اذا فهمت الفقرة السابقة فالتالي أسهل باختصار طريقة التعديل . ( أحضر الكائن المطلوب ..عدله ...أرسله ) مثلا لنعدل أحد المنتج السابق الذي أضفناه المسمى CCCCCC ليصبح اسمه XXXXX هذا الكود

Dim myProduct = From pro In MyDB.Products _ 
Where pro.ProductName = "CCCCCC" Select pro 
If myProduct.Count > 0 Then myProduct.First.ProductName = "XXXXXX" 
MyDB.SubmitChanges()

ثالثا حذف البيانات :

ايضا بنفس الطريقة السابقة : أحضر الكائن ثم احذفه ثم أخبر القاعدة (قاعدة البيانات طبعا ...) وهذا كود لحذف المنتج XXXXX :

Dim myProduct = From pro In MyDB.Products _ 
Where pro.ProductName = "XXXXXX" Select pro 
If myProduct.Count > 0 Then _ 
myDB.Products.DeleteOnSubmit(myProduct.First) 
MyDB.SubmitChanges()

ولحذف كل ما اضفناه في الأكواد السابقة لقاعدة بيانات Northwind حيث سنحذف Category التي تبدأ ب Arab ومنتجاتها بهذا الكود :

Dim myCat = From cat In MyDB.Categories _ 
Where cat.CategoryName Like "Arab*" Select cat 

If myCat.Count > 0 Then 
For Each cat In myCat 
MyDB.Products.DeleteAllOnSubmit(cat.Products) 
Next 
End If 

MyDB.Categories.DeleteAllOnSubmit(myCat) 
MyDB.SubmitChanges()

رابعا :نطاق العمليات Transactions :

اعتدنا دائما لإنشاء برنامج يعتمد عليه أن نستخدم عن تغيير البيانات كائنات Transaction خاصة عند حدوث خطأ ما أثناء ادخال بيانات مترابطة فيجب الغاء العملية برمتها ..فليس من المعقول أن نسجل الفاتورة مثلا ناقصة بعض الاغراض .

وبالنسبة ل Linq To SQL فهي تدعم Transaction داخليا فعند أي استدعاء ل SubmitChanges سيقوم مزود Linq تلقائيا بانشاء Transaction خاص بهذا الاستدعاء حيث ولدى حدوث أي خطأ فإن عملية تحديث البيانات سيتم الغائها تلقائيا .. جرب هذا الكود أن Category المقصودة لازالت موجودة . ( حيث تعمدت أن أولد خطأ عن طريق حذف كائن من Category مرتبط بكائنات من Product وهذا لا تسمح به قاعدة البيانات حيث يجب حذف الطرف الآخر من العلاقة ).

Dim myCat = From cat In MyDB.Categories Where cat.CategoryID = 2 

MyDB.Categories.DeleteAllOnSubmit(myCat) 

Try 
MyDB.SubmitChanges() 
Catch ex As Exception 
MsgBox("Error !! all changes canceled") 
End Try

ويمكن تعديل الكود السابق بحيث نتتبع الخطأ و نعالجه في جملة Catch ثم نستدعي SubmitChanges مرة أخرى.

وهناك طريقة أخرى عن طريق خاصية Transaction للكائن DataContext حيث بامكاننا استخدام نطاق Transaction من كائنات ADO.net وستكون كل العمليات التي ستتم ضمن هذا النطاق واذا عملنا RollBack ستلغى كل التغييرات .

بهذا ينتهي مقال اليوم ..امل أن يكون مفيدا للجميع .. إلى لقاء مع الموضوع القادم الذي سيكون عن ميزة رائعة يمكن الاستفادة منها في Linq وهي Extensions ..وايضا سنلقي نظرة أعمق على الكائن DataContext .

والسلام ...

المقال كاملا بصيغة PDF LINQ4b.pdf

1
#11

توسعة الوظائف Extensions

إن كل نوع بيانات أو فئة في VB2008 له مجموعة من الدوال كما اعتدنا مثلا ( String,Integer,List ) ونحن نستخدم هذه الوظائف بشكل اعتيادي في كل برامجنا .. ولكن ماذا لو احتجنا لتوسيع هذا النوع ليحتوي وظائف جديدة نحتاجها في البرنامج ؟ .. سابقا كنا ننجز هذا العمل باشتقاق فئة جديدة و اضافة الوظائف لها ولكن الآن يمكننا بسهولة إضافة وظيفة أو أكثر لنوع بيانات باستخدام Extensions .

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

ترجمة للكلام السابق : مهمتنا الحالية هي انشاء دالة (وظيفة ) نسميها JoinNames تقوم بعرض مجموعة حقول نصية بشكل حقل نصي واحد مفصول بفواصل . وسيكون مثالي من قاعدة بيانات NorthWind عرض الفئات Categories بحيث يكون بجانب كل سجل من Category مجموعة المنتجات Products التي تخص هذه الفئة مفصولة بفواصل .

فالنوع المطلوب توسعته هنا هو Product وبالأصح مجموعة Product يعني بلغة البرمجة IEnumerable( of Product)

الكود كالتالي بكل بساطة :

Imports System.Runtime.CompilerServices 
… 
… 
… 
Public Module Ext 
<Extension()> Public Function JoinNames(ByVal ProductList As IEnumerable(Of NorthWind.Product)) As String 

Dim Names = From pro In ProductList Select pro.EnglishName 

Dim NamesString = String.Join(",", Names.ToArray) 
Return NamesString 
End Function 

End Module

الان لنستخدم هذه الدالة الجديدة في مثالنا و نعرضها في datagrid :

Dim mySource = From cat In MyDB.Categories _ 
Let ProductsNames = cat.Products.JoinNames _ 
Order By cat.CategoryName _ 
Select Number = cat.CategoryID,Name =cat.CategoryName, _ 
Products = ProductsNames 

DataGridView1.DataSource = mySource

نظرةأعمق على DataContext

خصوصية الكائنات و تفردها مع Linq to SQL :

ان الكائن DataContext كما ذكرنا سابقا هو وسيط اتصال Linq To SQL مع قواعد البيانات فهو الذي يترجم ما نعمله بالكائنات إلى جمل SQL . وايضا من مهماته التحكم باحضار البيانات والتحقق منها ؟؟!! كيف ذلك !!

لكي لايحدث تضارب بالبيانات ولأسباب أخرى فإن DataContext لايكرر وجود نفس البيانات ... المعنى أنه لو استدعيت نفس مجموعة السجلات في مكانين مختلفين وبطريقتين مختلفتين فسيكون لديك في الذاكرة نفس المجموعة من السجلات !! وهذا مثال :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 

''Ado.net Objects 
Dim con As New SqlServerCe.SqlCeConnection("Data Source = Northwind.sdf") 
Dim com1 = con.CreateCommand 
com1.CommandText = "Select Top (1) * From Categories Where [Category ID] = 3" 
con.Open() 
Dim Cat1 = com1.ExecuteResultSet(SqlServerCe.ResultSetOptions.None) 
Dim Cat2 = com1.ExecuteResultSet(SqlServerCe.ResultSetOptions.None) 
con.Close() 
''LINQ to SQL DataContext 
Dim MyDB As New NorthWind.NorthWind("Northwind.sdf") 
MyDB.Log = Console.Out 
Dim myCat = From catg In MyDB.Categories _ 
Where catg.CategoryID = 3 Select catg 
Dim Cat3 = myCat.First 
Dim Cat4=MyDB.Categories.Where(Function(cat) cat.CategoryID = 3).First 

'' فحص التساوي 
Console.WriteLine("Cat1,Cat2 are Equals ? " & Cat1.Equals(Cat2)) 
Console.WriteLine("Cat3,Cat4 are Equals ? " & Cat3.Equals(Cat4)) 

End Sub

نحن تعودنا في ADO,Net أن يكون الكائتنين مختلفين رغم أنهما متساويين بالمحتويات جرب الكود السابق وسترى أن كائني resultset متساويين ( للتذكرة كائن ResultSet مثل DataReader ولكنه قابل للكتابة )

ما أهمية ذلك ؟؟؟ من ذلك نسنتنج أن تنتبه عند أجرائك تعديلات على الكائنات فحتى الكائنات التي كنت تعتقد أنها تحتفظ بالقيم الأصلية قبل التعديل ستكون قد تعرضت للتغير من قبل datacontext .

ما الحل ؟؟ خذ هذ القاعدة و طبقها دائما في Linq to SQL

ملاحظة هامة :

دائما انشئ كائن جديد DataContext لاستعلاماتك يعني لاتعامله مثل Connection وتصنع كائنا واحدا لكل التطبيق انما اجعله كائنا على مستوى الاجراء أو الوظيفة Procedure Level كما في جميع امثلتي السابقة اذا لاحظتم .

التحميل من قاعدة البيانات :

عندما نكتب استعلاما ما من استعلامات Linq to SQL فإننا لانقوم فعليا الا بتعريف الاستعلام وقولبة المتغيرات لاستقبال نتائج الاستعلام . ويتم تنفيذ الاستعلام ( أي ترجمته لجملة SQL وارسالها لقاعدة البيانات ) لعرض النتائج عند الحاجة لذلك ويمكنك ان تلاحظ ذلك بمشاهدة نتائج نافذة OutPut اذا كنت وضعت السطر

MyDB.Log = Console.Out

مثلا اذا كتبنا السطر التالي

Dim myCat = From catg In MyDB.Categories Select catg

فهو عبارة عن تعريف الاستعلام وتنفيذه الفعلي يتم عندما يحتاج البرنامج للبيانات وذلك أما بحلقة For Each

أو عند استدعاء الأمر ToList أو عند اسناده ل datasource جرب كتابة كود لذلك وتتبع تنفيذ البرنامج بوضع BreakPoint و سترى متى يتم عرض جملة SQL .

فإذا أردنا أن يتم التنفيذ فورا فقط حول السطر السابق إلى ما يلي

Dim myCat = (From catg In MyDB.Categories Select catg).Tolist

والحالة الأخرى التي يتم فيها ارسال جملة SQL هي عند اعتماد التغييرات باستخدام SubmitChanges .

وأما بالنسبة للكائنات الفرعية ( أي المرتبطة بالعلاقات ) فهناك عدة خيارات :

تحميل الكائنات الفرعية عند الحاجة لذلك : وهو الخيار الافتراضي وهنا تكون خاصية ObjectrackingEnabled معينة للقيمة True وهنا يتم تحميل أي كائن فرعي (جدول مرتبط ) عند اللزوم .

تحميل الكائنات الأساسية فقط : عندها يتم تحميل الكائنات الأساسية فقط ولايتم تحميل الكائنات الفرعية وذلك باسناد القيمة False للخاصية ObjectrackingEnabled. وتصبح البيانات للقراءة فقط !! .

التحكم بتحميل الكائنات : وذلك عن طريق خيارات التحميل Load Options فنتحكم نحن بما يتم تحميله من قاعدة البيانات مع كل كائن . مثلا بامكاننا أن نخبر DataContext أنه عند تحميل مجموعة Orders أن يحمل مع كل كائن Order مجموعة OrdersDetails و هنا فإن DataContext يرجع لخاصية ObjectTrackingEnabled لمعرفة ما إذا كان يجب تحميل بقية الكائنات الفرعية أم لا .

لتوضيح الأمر أكثر سأناقش هذه الحالات لاحقا ثم أعرض مثال توضيحي. وقبل ذلك فإن طريقة استخدام LoadOptions كالتالي :

لنفترض أنني أريد تطبيق المثال في الأسطر السابقة أي تحميل كل كائن Orders مع كائن OrdersDetails :

Dim MyDB As New NorthWind.NorthWind("Northwind.sdf") 
MyDB.Log = Console.Out 
''انشاء كائن LoadOptions 
Dim myopt As New System.Data.Linq.DataLoadOptions 
''Order تحديد ما نريد تحميله من العلاقات للكائن 
myopt.LoadWith(Of NorthWind.Order)(Function(o As NorthWind.Order)o.OrderDetails) 
'' DataContextربط الخيارات السابقة مع 
MyDB.LoadOptions = myopt

قد يتسائل شخص ما ما فائدة ذلك ؟؟؟ لماذا لانترك كل شي كما هو افتراضيا وندع DataContext يطلب الكائنات التي نحتاجها !!؟؟!

وجوابي هو : افترض أن لديك دالة تكرارية تستدعي كائنات Order و OrderDetails فسيكون الناتج لدينا حوالي 100 استعلام sql سيرسل لقاعدة البيانات بينما بامكانك تحديد تحميل OrderDetails مباشرة مع الكائن Orders وعندها لن يرسل لقاعدة بياناتك سوى استعلام واحد جرب ذلك ولاحظ الفرق في الأداء.(كثيرون يشتكون من أداء Linq والسبب هو أن كودهم يواصل ارسال الاستعلامات ويقتل الأداء .

الآن لنوضح كل ما ذكرناه سابقا بمثال عملي ....

ومثالي هذا الكود وهو لايعمل شيئا سوى تحميل كائنات من قاعدة البيانات ولكن تتبع تنفيذه و راقب نافذة OutPut لترى مايحدث توضيح الخطوات موجود مع الكود :

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 

'''''''''''''''' تجربة 1 
Dim MyDB1 = CreateDataContext() 
''تمكين تحميل الكائنات عند الطب 
MyDB1.ObjectTrackingEnabled = True 
''First سيتم تنفيذ الاستعلام مباشرة لوجود 
''OutPut هنا راقب في الخطوة الاستعلام الذي يتم إرساله لقاعدة البيانات من نافذة 
Dim Q1 = (From ord In MyDB1.Categories Select ord).First 
''هنا تم تنفيذ استعلام اخر كما ترى 
Dim Q2 = (From prod In Q1.Products Select prod).ToList 
'' النتيجة وجود كائنات 
MsgBox(Q2.Count) 

'''''''''''''''''' تجربة 2 
Dim MyDB2 = CreateDataContext() 
'' الغاء تحميل الكائنات 
MyDB2.ObjectTrackingEnabled = False 
'' لاحظ نفس جملة الاستعلام السابقة 
Dim Q3 = (From ord In MyDB2.Categories Select ord).First 
'' لاحظ هنا لايتم ارسال أي شيء 
Dim Q4 = (From prod In Q3.Products Select prod).ToList 
'' النتيجة خالية 
MsgBox(Q4.Count) 

Dim myOpt As New System.Data.Linq.DataLoadOptions 
''Products تعريف كما ذكرناه تحميل الكائنات الفرعية 
''Category للكائن 
myOpt.LoadWith(Of NorthWind.Category)(Function(cat As NorthWind.Category) cat.Products) 

'''''''''''''''' تجربة 3 
Dim MyDB3 = CreateDataContext() 
''تمكين التحميل عند الطلب 
MyDB3.ObjectTrackingEnabled = True 
'' تحديد خيارات التحميل 
MyDB3.LoadOptions = myOpt 
'' الآن راقب الاستعلام كيف اختلف 
Dim Q5 = (From ord In MyDB3.Categories Select ord).First 
'' لايوجد استعلام هنا لأنه سبق تحميلها 
Dim Q6 = (From prod In Q5.Products Select prod).ToList 
'' يوجد نتائج 
MsgBox(Q6.Count) 

'''''''''''''''' تجربة 4 
Dim MyDB4 = CreateDataContext() 
'' الغاء التحميل عند الطب 
MyDB4.ObjectTrackingEnabled = False 
'' خيارات التحميل 
MyDB4.LoadOptions = myOpt 
'' لاحظ جملة الاستعلام ايضا 
Dim Q7 = (From ord In MyDB4.Categories Select ord).First 
'' لااستعلام ينفذ 
Dim Q8 = (From prod In Q7.Products Select prod).ToList 
'' ايضا النتائج موجود 
MsgBox(Q8.Count) 

End Sub 
Function CreateDataContext() As NorthWind.NorthWind 
'' DataConteXtدالة بسيطة لإنشاء 
Dim myDB As New NorthWind.NorthWind("Northwind.sdf") 
myDB.Log = Console.Out 
Return myDB 
End Function

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

مع أني لاحظت عدم وجود أي أسئلة أو استفسارات وقد كان أحد أساتذتي عند كل نهاية درس يسأل "هل من سؤال؟" وعندما لا أحد يسأل يقول"إما كلكم فاهمين ..... أو ولا واحد كان سامعني "

المهم أن يكون طرحي مفيدا ولاتنسونا من الدعاء .ولم نتنهي بعد حيث لدي أيضا بعض الأفكار و التقنيات لاستخدام Linq to SQL وسأطرحها على شكل مواضيع مستقلة ..... والسلام عليكم

الموضوع بصيغة PDF LINQ5b.pdf

#12
مهند عبدالحفيظ كتب:

السلام عليكــم ورحمـة الله وبركاتــه

سأبدأ من الألف إلى الياء وذلك للمبتدئين في استخدام LINQ

خطوات عمل البرنامج :

  1. انشاء برنامج جديد فارغ من نوع Windows Form Application .
  2. إضافة و تصميم قاعدة البيانات عن طريق Server Explorer .
  3. انشاء فئات العمل ل LINQ عن طريق SQLMetal
  4. تطبيق استعلامات LINQ للتعامل مع الباينات ( عرض-حذف-اضافة-تعديل)

طبعا الخطوة الأولى سهلة ولا تحتاج لشرح ... وبعد انشاء البرنامج سيظهر لك نموذج وحيد Form1 اتركه كماهو ونبدأ بالخطوة الثانية ....

بناء وتصميم قاعدة البيانات

لانشاء قاعدة بيانات جديدة : نذهب للقائمة Project ونختار Add New Item و ثم نختار Local DataBase ونسميها اي اسم .فيظهر معالج الاتصال بقاعدة البيانات اضغط Cancel لأننا لا نريد انشاء DataSet .سنجد ملف الداتا قد اضيف لنافذة Solution Explorer نضغط عليه فيفتح لنا ServerExplorer ثم نضيف الجداول لقاعدة البيانات وننشيء العلاقات الازمة .

إضافة قاعدة بيانات موجودة : وللسهولة ساستخدم قاعدة بيانات NorthWind.sdf الشهيرة حيث نختار من قائمة Project ثم Add Existing Item ثم تضيف ملف NorthWind.sdf التي تجدها في المجلد :

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Samples

وسيظهر معالج الاتصال بقاعدة الباينات فنضغط Cancel .

الان هذه الخطوة مهمة لكل قواعد البيانات المحلية : حيث أن الفيجوال ينشيء قاعدتي بيانات احدهما في مجلد البرنامج والثانية للتنفيذ في مجلد Debug وبالتالي فعندما نقوم باضافة بيانات اثناء تنفيذ البرنامج نتفاجأ انها اختفت عندما نستعرض البيانات في server explorer لذلك نقوم بالتالي : من نافذة المشروع Solution Explorer اختار ملف قاعدة البيانات وفي الخصائص عدل الخاصية Copy to Output Directory إلى Do not Copy .

الان نحفظ المشروع تمهيدا للخطوة الثالثة

انشاء فئات العمل مع LINQ

ما هي فئات العمل مع LINQ ؟

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

ان البيئة المثالية لانشاء فئات العمل هي O/R Designer ولكن لا اعلم لماذا لم تضف ماايكروسوفت دعم قواعد بيانات SQL Server CE له!!؟ وبالتالي سنستخدم البرنامج البديل وهو SQLMetal.exe وهو يأتي مع الفيجوال :

  1. اولا نغلق البرنامج ونذهب للمجلد C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
  2. ثم ننسخ الملف SQLMetal.exe إلى مجلد البرنامج الذي فيه ملف Northwind.sdf .
  3. نبقى في مجلد برنامجنا وننشئ اختصار جديد لملف SQLMetal.exe الذي نسخناه
  4. نفتح خصائص الاختصار الذي انشأناه وفي خانة Target (الهدف) نضع بعد اسم البرنامج الاوامر التالية :
     /namespace:NorthWind /code:NorthWind.vb /Language:vb /pluralize NorthWind.sdf

  5. للتوضيح أكثر تصبح خانة الهدف كالتالي :
    "C:\Users\Muhannad\Documents\Visual Studio 2008\Projects\SampleLINQ\SampleLINQ\SqlMetal.exe" /namespace:NorthWind /code:NorthWind.vb /Language:vb /pluralize NorthWind.sdf

  6. والان نقوم بتشغيل ملف الاختصار ستظهر نافذة موجه الاوامر للحظات ثم تختفي وسنجد أنه لدينا ملف جديد في المجلد اسمه NorthWind.vb وهو المطلوب .
  7. نفتح مشروعنا ونختار من قائمة Project اضافة الملف Add existing Item و نذهب لمجلد البرنامج ونضيف ملفنا الجديد NorthWind.VB .
  8. بقي خطوة أخيرة حيث يتطلب اضافة refrence للبرنامج ل System.Data.Linq ..الطريقة لم لا يعرف من قائمة Project ثم Add refrence ثم تحت علامة .NET ستجد System.Data.Linq أضفها للمشروع .

ملاحظة هامة : يجب اعادة انشاء ملف تالفئات عند أي تغيير في تصميم قاعدة البيانات مثلا اضافة جدول جديد أو أعمدة جديدة لجدول موجود وعندها لاتحتاج الا لتشغيل الاختصار السابق وانتبه أن لاتكون قاعدة البيانات مفتوحة في مكان اخر كالفيجوال مثلا .

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

مع التحية

مشكــور اخويـ ع المجهــود

عندي بعض الاستفسارات..

ياريت تعرفني اكثر علىsql metal.exe يعني هي عملها الاساسي شو وهل لها استخدامات اخرى

في الخطوة اللي كاتب فيها نبقى في مجلد برنامجا وننشى اختصار جديدلsqlmetal.exe تقصد مجلد برنامج شو

ياريت تفيدني اخوي وتسلم

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