103
م ي ح ر ل ا ن م ح ر ل له ا م الس ب. : ه ي ل ا ت ل ا اط ق ن ل ا ي ف ات ان ت% لب واعد ا ق ع م ل م عا ن ل ا ي ف ا ن ف هد4 ص ا خ ل ت8 ت1 . ات ان ت% لب ا اعدة صدر ق م ب صال تلا ا- 2 ة4 يH ب% ب ي ف رة ف و ت م ل ا دوات4 لال ا لا خ ن م ي تT ش رق ط ت ها ض ر ع ها و ب ي لت ا ات ان ت% لب ا راءة ف- Microsoft.NET . 3 و4 ا دة دن خ ات ان ت% ت ه اف ضb و ا4 ا ات ان ت% لب ة ا م هد ي ف ل ب عد تال ل خ ن م هاT ث ت حد ت و ات ان ت% لب ا ه ج ل عا م- ها . ث ف وت غ ر م ر ي غ ات ان ت% ت ف خد4 . هT حدث م ل ا ات ان ت% لب اr ظ ف ح- 5 ال ق نw تلا و ا4 ا ق ب سا ل ل ا ح س ل ل ودة ع ل4 و ا4 ا ي ل ا ت ل ل ا ح س ل ل ال ق نw تلال ا لا خ ن م ات ان ت% لب ا ي ف حار تb لا ا- ر . ي خ4 لا ل ا ح س ل ل ال ق نw تلا و ا4 ول ا4 لا ل ا ح س ل ل6 . ح يT ش ر لي ل ر ت لا ق ع ضال و ل خ ن م ر س ب و وله ه س ب ات ان ت% لب ا ن عT ث ح ب ل ا- 7 ها . ث ح ل عا م ها و ض ر ع دول و خ ن م رT كي4 ا ي ف ه لاف ع ل ا ات د ات ان ت% لب ظ ا رت- 8 . ات ان ت% لب ل صه خ مل لر ا ت ار ق ن ل ا اغه ت ط- ============= -: ه داث ت ل ا ن ع ة د ت ت* ADO.NET : ماء س4 لال ا ا ح م ي ف وله مT ش م ات4 ت ف ل ا ن م وغه م ج م ي هSystem.Data ي لb ول ا ض و ل ا ها ض ر ع

ADO.Net - Arabic

Embed Size (px)

DESCRIPTION

How To Use ADO.Net

Citation preview

Page 1: ADO.Net - Arabic

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

تتلخص أهدفنا في التعامل مع قواعد البيانات في النقاط التالية :- االتصال بمصدر قاعدة البيانات .1 - قراءة البيانات التي بها وعرضها بطرق شتى من خالل األدوات2

.Microsoft.NETالمتوفرة في بيئة - معالجة البيانات وتحديثها من خالل تعديل قيم هذه البيانات أو إضافة3

بيانات جديدة أو حذف بيانات غير مرغوب فيها .- حفظ البيانات المحدثة .4 - اإلبحار في البيانات من خالل االنتقال للسجل التالي أو ألعودة للسجل5

السابق أو االنتقال للسجل األول أو االنتقال للسجل األخير .- البحث عن البيانات بسهولة ويسر من خالل وضع فالتر للترشيح .6- ربط البيانات ذات العالقة في أكثر من جدول وعرضها ومعالجتها .7- طباعة التقارير الملخصة للبيانات .8

=============البداية :-

:ADO.NET* نبذه عن System.Dataهي مجموعة من الفئات مشمولة في مجال األسماء

والتي تمثل بياناتData Sourcesغرضها الوصول إلى مصادر البيانات Microsoftمحفوظة تحت أنظمة قواعد بيانات متعددة األنواع ) مثل

Office Access أو SQL Server أو Oracleمما يعني قدرتك على ) الوصول إلى أي قاعدة بيانات مهما كانت الشركة المنتجة لها . ) أ. تركي

العسيري( . باستخدام مزودات البيانات لالتصال بمصادر البياناتADO.NETوتقوم

ومن ثم استرجاع هذه البيانات وتعديلها وإعادتها لمصادرها وحفظها هناك )أ. خالد الجديع ( .

* االتصال بقواعد البيانات:- للوصول إلى البيانات المخزنة في قاعدة البيانات ) والتي سوف تكون في

Microsoft الخاص ببرنامج MDBدرسنا هنا عبارة عن ملف من نوع Office Accessوالقراءة منها أو الكتابة فيها يجب أن نكو�ن اتصال )

،Connectionناجح معها ، وذلك يتم من خالل كائن االتصال المسمى ولتجهيز هذا الكائن نحتاج إلى أعطائه معلومات عن ملف قاعدة البيانات

الذي نريد أن نتصل به ) من أهمها على سبيل المثال مزود البيانات وخادم البيانات واسم ومكان قاعدة البيانات و كلمة المرور مع كلمة السر إن

وجدت ( ، وهذه المعلومات تكو�ن لنا بما يسمى سلسلة االتصال )Connection String. وهي عبارة عن أحد خصائص كائن االتصال )

* سلسلة االتصال : ( الضروريةParametersوهي عبارة عن مجموعة من العوامل )

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

يهمنا من هذه العوامل ما يلي :

Page 2: ADO.Net - Arabic

-Providerوهو عبارة عن اسم مزود البيانات وسوف نذكر هنا نوعين : � ، النوع األول وهو للتعامل معMicrosoft.Jet.OLEDB.4.0األكثر انتشارا

SQLOLEDB ، والثاني Microsoft Office Accessقواعد بيانات برنامج .SQL Serverوهو مخصص للتعامل مع قواعد بيانات برنامج

-DataSourceوهو اسم خادم البيانات ) أللذي يحتوي على جداول : البيانات التي نريد أن نتصل بها ( ، ونجد أن خادم البيانات في برنامج

Microsoft Office Accessهو اسم ملف قاعدة البيانات الذي يحمل Server فهو عبارة عن اسم الـ SQL Server ، بينما برنامج MDBامتداد

المثبت على الجهاز . -Intial Catalogوهو عبارة عن اسم قاعدة البيانات الموجوده في :

.SQL Serverالخادم بالنسبة لبرنامج -UserID/Passwordوهو عبارة عن اسم المستخدم وكلمة المرور :

لقاعدة البيانات في حالة وجود قيود أمنية عليها .: � ولعل المثالين التاليين تجعل الصورة واضحة جدا

:1مثال ..Microsoft Office Accessسلسة اتصال بملف قاعدة بيانات برنامج

كودProvider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\ MymdbFile.mdb;User ID=Admin;Jet OLEDB:Database Password=You'rePassword;

:2مثال ..SQL Serverسلسة اتصال بملف قاعدة بيانات برنامج

كودProvider=SQLOLEDB;Data Source=SQL Server DB;Initial Catalog=Northwind;User ID=You'reUserName;Password=You'rePassword

بعد التعرف على سلسلة االتصال يجب أن نتعرف على نوعي� طريقة

االتصال بقاعدة البيانات ..

* نوعي� طريقة االتصال بقواعد البيانات :

من الجدير بالذكر أننا لو أردنا أن نتصل على قاعدة البيانات بواسطة

ADO.NETيجب أن نختار طريقة االتصال المناسبة الحتياجاتنا ، فلدينا

( وConnection Orientedطرقتين لالتصال وهما االتصال المتصل )

( . ولكل منهماConnectionless Orientedاالتصال المنفصل )

امتيازاته وعيوبه و إستراتجياته الخاصة به في العمل ، غير أن األخير يعتبر

األمثل في التعامل مع قواعد البيانات ، وهنا بالتحديد يضيع أغلب من

.ADO.NETيرغبون تعلم برمجة قواعد البيانات من خالل

Page 3: ADO.Net - Arabic

-----------------------------------------------------------------------------------

توقفنا في حديثنا الماضي أن أغلب من يرغبون تعلم برمجة قواعد

يضيعون في التفريق بين االتصال المتصل )ADO.NETالبيانات من خالل

Connection Oriented ( و االتصال المنفصل ) Connectionless

Orientedوالسبب في اعتقادي هو ضعف فهم اآللية التي يعمل بها . )

كل منهما من ناحية ، والخلط بينهما من ناحية أخرى . ولكي نزيل هذه

المشكلة سوف نتحدث عن كل منهما بشكل مستقل ..

وقبل ذلك يجب أن نوضح أمر مهم وهو : أنه عند بدأ مشروع جديد

لالتصال بقاعدة البيانات يجب قبل كل شيء أن نستدعي فضاء األسماء

( الذي نتعامل معه ، والذي تندرجProviderالمناسب لمزود البيانات )

تحته كائناته الخاصة به لالتصال بقاعدة البيانات و ومعالجتها ، ومن

مميزات استدعاء فضاء األسماء أنه يغنينا عن كتابة مسار الكائنات التي

سوف نستخدمها ، فقط نكتب اسم الكائن ..

نستدعيMicrosoft Office Accessفعند التعامل مع قواعد بيانات

وذلك بكتابة الكود التالي في أعلىSystem.Data.OleDbفضاء األسماء

صفحة الكود :

كودImports System.Data.OleDb

وتندرج تحته مجموعة من الكائنات ولكن كل ما يهمنا منها كمبتدئين مايلي :

OleDbCommand , OleDbConnection , OleDbDataAdapter , OleDbDataReader , OleDbParameter ,

OleDbCommandBuilder , OleDbTransaction. , OleDbException.

نستدعي فضاء األسماءSQL Serverوعند التعامل مع قواعد بيانات System.Data.SqlClientوذلك بكتابة الكود التالي في أعلى صفحة

الكود :

Page 4: ADO.Net - Arabic

كودImports System.Data. SqlClient

وتندرج تحته مجموعة من الكائنات ولكن ما يهمنا منها كمبتدئين ما يلي :SqlCommand , SqlConnection , SqlDataAdapter ,

SqlDataReader , SqlParameter , SqlCommandBuilder , SqlTransaction. SqlException.

يستطيعون أن يكملواSQL Serverمالحظة : اإلخوة الذين يستخدمون OleDbمعنا الدرس دون مشاكل ، وكل ما عليهم هو أن يستبدلوا عبارة

.Sqlبعبارة

( :Connection Oriented* االتصال المتصل )

وتتلخص فكرته في أن نقوم بإجراء اتصال مع قاعدة البيانات ، وبعد قبوله نقوم بفتح االتصال ثم نقوم بتنفيذ مجموعة من األوامر التي نحتاجها ) مثل قراءة البيانات من أجل عرضا للمستخدم ، أو تحديث البيانات من إضافة و تعديل حذف وحفظ ، أو إلغاء عملية التحديث ، أو البحث عن بيانات معينة

أو أإلبحار والتجول في البيانات ( وبعد االنتهاء نقوم بإغالق االتصال ،� � الن معظم مصادر البيانات تدعم عددا ويعتبر إغالق االتصال ضروريا

� من االتصاالت المفتوحة . وهذا يعني أننا يجب أن نحافظ على محدودااالتصال حتى ننتهي من الهدف الذي تم من أجله االتصال .

وهو مناسب " في حاله بناء التطبيقات المفردة ، أي عندما يكون للنظام مستخدم واحد وتوجد واجه المستخدم ومخزن قاعدة البيانات على نفس

(VB.NET ، مشرف منتدى ال SOLO.NETالجهاز . " ) أ.

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

� مهم من موارد النظام ، ويترتب علية تدني أداء هذه يستهلك جزءا� من االتصاالت � محدودا التطبيقات . وألن معظم مصادر البيانات تدعم عددا� . ويعد ذلك من أكبر عيوب هذا النوع باإلضافة المفتوحة كما أسلفنا سابقا

إلى أنه يتطلب كتابة الكثير من األكواد البرمجية كما سوف نشاهد في الجزء العملي من الدرس ، وذلك يعد عائق كبير أمام صيانة الكود وتحديثه

من وقت ألخر . ولعمل اتصال من هذا النوع نحتاج إلى ثالث كائنات أساسية نستخدمها

على النحو التالي :

: من أجل االتصال بقاعدة البياناتOleDbConnection- كائن االتصال 1.

- فتح االتصال بقاعدة البيانات .2 : في اعتقادي أنه يمثل القلبOleDbCommand- كائن األوامر 3

لالتصال المتصل ، وهو من أجل تنفيذ عملية قراءة البيانات المخزنة في قاعدة البيانات ، أو تحديثها ) من إضافة وتعديل وحذف ( ، ويعتمد في

Page 5: ADO.Net - Arabic

تكوينه على وجود اتصال مفتوح مع قاعدة البيانات ، وعلى جملة االستعالم ) وهي لغة قياسية لبناء ومعالجة قواعد البيانات ومحتوياتها ،SQLالبنيوية

وتتضمن هذه اللغة تعليمات من أجل إضافة ، تعديل ، حذف ، ترتيب ، واختيار سجالت ( . ومن أهم خصائصه :-

-Connectionويجب أن يحمل اسم االتصال الذي سوف يستخدمه : كائن األمر .

-CommandType وله ثالثة قيم ، القيمة : Textلتنفيذ جملة استعالم ( ) لتنفيذ إجراء مخزن فيStoredProcedur ( ، القيمة SQLبنيوية

) للتعامل مع جدول واحد ( .TableDairectقاعدة البيانات ( ، القيمة فقط وهي ما تهمناTextمالحظة : سوف نستخدم في درسنا القيمة

كمبتدئين .

-CommandTextويعتمد على القيمة التي اخترناها في الخاصية : ( ، لذلك سوف يكون لدينا ثالث مدخالتCommandTypeالسابقة )

متناسبة معها على التوالي ، اإلدخال األول عبارة عن جملة استعالم بنيوية والتي سوف يتم تنفيذها سواء الختيار أو تحديث السجالت ، المدخل الثاني

عبارة عن اسم اإلجراء المخزن في قاعدة البيانات والذي نريد تنفيذه ،والمدخل الثالث عبارة عن اسم الجدول الذي نريد التعامل معه .

-Parametersويستخدم للوصول إلى معامالت اإلدخال و اإلخراج : والقيم العائدة .

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

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

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

( وهي أحد خصائص كائن األمرExecuteNonQueryالطريقة الثانية ) وتقوم بتنفيذ استعالم بنيوي يقوم بتحديث قاعدة البيانات ) من إضافة ،

تعديل ، و حذف ( أو تكوين قاعدة بيانات والنتيجة التي ترجع هي عددالصفوف المتأثرة باألمر .

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

: ويقوم بقراءة تيار منOleDbDataReader- كائن قراءة البيانات 4 البيانات القابلة للقراءة فقط وفى اتجاه واحد يكون لألمام فقط . ويعتمد

Page 6: ADO.Net - Arabic

في تكوينه على وجود كائن أمر مبني على جملة استعالم مصممة الختيارسجالت . ومن أهم خصائصه :

-Readومهمتها هي توجه قارئ البيانات إلى قراءة الصف األول من : إذا لم يوجد صف .False إذا وجد صف أو Trueالنتائج ، وترجع القيمة

-Itemومهمتها هي استرجاع قيمة العمود إما باستخدام أسم العمود أو : رقمه .

-GetValues. � : ومهمتها هي استرجاع قيمة الصف كامال

-isDBnullومهمتها هي اختبار فيما إذا كانت البيانات تحتوي على قيم : Null.

-Close. ومهمته هي إغالق كائن قارئ البيانات وال يقوم بإغالق االتصال : � إغالق قارئ البيانات عند االنتهاء منه الن كائن مع مالحظة أنه يجب دائما األوامر إذا كان يحتوي على معامالت إخراج أو قيم جديدة لن يكون في

.DataReaderاإلمكان التعامل معها إلى أن يتم االنتهاء من إغالق كائن

- إغالق االتصال بقاعدة البيانات .5

* وهنا نصل للجانب العملي من الدرس :

سوف نركز في الجانب العملي على الثالثة طرق التي يتم بها العمل في والذي قلنا فيما سبق أنه يمثل القلب .OleDbCommandكائن األوامر

، ماذا لو فرضنا أننا نريد أن نقرأExecuteReader : الطريقة 1مثال مجموعة من البيانات الموجودة في ملف قاعدة البيانات مصمم ببرنامج

Microsoft Office Access ( والمسمى Noteوالذي من المفترض أن ) يوجد في نفس مسار مشروعنا ، وهذا الملف محمي بكلمة المرور )

ado.net ( وهو يحتوي على جدول اسمه ) Informationوالذي يحتوي ) ويحمل خاصية الترقيم التلقائي ويعدIDبدوره على الحقول التالية )

ويحمل خاصيةPhone ويحمل خاصية كونه نص ، Nameمفتاح أساسي ، كونه رقم ( ، ثم نعرض هذه البيانات في مربعات نص ، فكما تعلما سوف

يكون العمل على النحو التالي ...

� : نقوم بفتح مشروع جديد و نضيف مربعات النص التي سوف نعرض أوال ...Informationفيها قيم الحقول الموجودة في الجدول

� : استدعاء فضاء األسماء الخاص بمزود بيانات برنامج MicrosoftثانياOffice Access.. وذلك بكتابة الكود التالي في أعلى صفحة الكود ،

Page 7: ADO.Net - Arabic

كودImports System.Data.OleDb

: � ثالثا Declarationsالتصريح عن الكائنات التي نحتاجها كمتغيرات في منطقة

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

التالي ...

كودDim Conn As New OleDbConnection)"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\ ConnectedMode\Note.mdb;User ID=Admin;Jet OLEDB:Database Password=ado.net"(

\:Cولكي ال نجعل برنامجنا الذي نتدرب علية مقيد بمسار ثابت وهو " ConnectedMode\MyNote.mdbنستطيع أن نجعله أكثر مرونة "

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

DataDirectory.. بحيث يصبح الكود السابق كما يلي "|

كودDim Conn As New OleDbConnection)"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Note.mdb;User ID=Admin;Jet OLEDB:Database Password=ado.net"(

كما في الكودMyCmdثم نقوم بالتصريح عن كائن األوامر وليكن اسمه التالي ..

كودDim MyCmd As New OleDbCommand

كما فيMyReaderثم نقوم بالتصريح عن كائن القراءة وليكن اسمه الكود التالي ..

كودDim MyReader As OleDbDataReader

� : في حدث تحميل النموذج نقوم بفتح االتصال .. رابعا

كودConn .Open

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

Page 8: ADO.Net - Arabic

في الجزء ألنضري من الدرس ، وذلك من خالل الكود التالي ..

كودMyCmd.Connection = ConnMyCmd.CommandType = CommandType.TextMyCmd.CommandText = "SELECT ID, Name, Phone FROM Information ORDER BY Name;"

� : نقوم بتهيئة كائن القراءة ، وذلك بإسناد الطريقة سادساExecuteReader التابعة لكائن األمر ( MyCmdإلية ، كما في )

الكود ..

كودMyReader = MyCmd.ExecuteReader

� : قبل إسناد قيم الحقول إلى مربعات النص نتحقق من أن كائن سابعا .. IFالقراءة وجد صفوف تحتوي على بيانات من خالل أداة الشرط

Then .. Else .. End If وباستخدام الخاصية Readوفي حالة توفر ، البيانات نقوم بإسناد قيمة كل حقل لمربع النص الخاص به من خالل

، كما في الكود التالي ..Itemالخاصية

كودIf MyReader.Read Then   txtID.Text = MyReader.Item)"ID"(   txtName.Text = MyReader.Item)"Name"(   txtPhone.Text = MyReader.Item)"Phone"(Else   MsgBox)" Empty ", MsgBoxStyle.Exclamation(End If

� من كائن القراءة وكائن االتصال ، كما في الكود التالي ... � : إغالق كال ثامنا

كودMyReader.Close)(Conn.Close)(

، استنادا للمثال السابق ماذا لوExecuteNonQuery : الطريقة 2مثال أردنا تحديث بياناتنا ) إضافة ، تعديل ، و حذف ( ، إذا فلنتابع شرح هذا

المثال ..� : نضيف ثالثة ) والثانيbtnAddNew ( ، ونسمي األول Buttonأوال

btnUpdate والثالث btnDelete. � : في حدث النقر لـ نقوم بما يلي ..btnAddNewثانيا

- نقوم بفتح االتصال ..1

كودConn .Open

Page 9: ADO.Net - Arabic

) باستخدامInsertCommand- نقوم بتهيئة كائن أمر جديد ونسميه 2 Parametersجملة استعالم بنيوية تقوم بإضافة بيانات مخزنة في

) ونرمز لها بالرمز ? ( لحقول معينة من الجدول الموجود في قاعدة البيانات ( كما ذكرنا في الجزء ألنضري من الدرس ، وذلك من خالل الكود

التالي ..

كودDim InsertCommand As New OleDbCommandInsertCommand.Connection = ConnInsertCommand.CommandType = CommandType.TextInsertCommand.CommandText = "INSERT INTO Information)Name,Phone( VALUES)?,?(;"

ألنه له خاصية الترقيم التلقائي .IDمالحظة : لم نضيف أي قيمة للحقل

الموجودة في جملة االستعالم منParameters- نقم بإعطاء قيم للـ 3 التابعة لكائن األمر ، وذلك بعد تنظيفه منParametersخالل الخاصية

مستخدمةParameters ) فيما إذا كانت هناك أي Parametersإي .. ) � سابقا

كودInsertCommand.Parameters.Clear)(InsertCommand.Parameters.AddWithValue)"?", txtName.Text(InsertCommand.Parameters.AddWithValue)"?", txtPhone.Text(

والتي سوف تقوم بتنفيذExecuteNonQuery- نطبق الطريقة 4استعالم تحديث الجدول ..

كودInsertCommand.ExecuteNonQuery)(

ألننا انتهينا منه وحتى الInsertCommand- نتخلص من كائن األمر 5 يستهلك جزاء من موارد النظام ، ثم نغلق االتصال بقاعدة البيانات

ونعرض رسالة بنجاح العملية ..

كودInsertCommand.Dispose)(Conn.Close)(MsgBox)" OK ", MsgBoxStyle.Information(

� : في حدث النقر لـ نقوم بما يلي ..btnUpdateثالثا- نقوم بفتح االتصال ..1

كودConn .Open

Page 10: ADO.Net - Arabic

) باستخدامUpdateCommand- نقوم بتهيئة كائن أمر جديد ونسميه 2 Parametersجملة استعالم بنيوية تقوم بتحديث بيانات مخزنة في

) ونرمز لها بالرمز ? ( لحقول معينة من الجدول الموجود في قاعدة كمعرف للسجل الذي نريدIDالبيانات وذلك اعتمادا على قيمة الحقل تحديثه ( ، وذلك من خالل الكود التالي ..

كودDim UpdateCommand As New OleDbCommandUpdateCommand.Connection = ConnUpdateCommand.CommandType = CommandType.TextUpdateCommand.CommandText = "UPDATE Information set Name=? , Phone=? WHERE Id =?;"

ألنه له خاصية الترقيمIDمالحظة : لم نقوم بتعديل قيمة الحقل التلقائي .

الموجودة في جملة االستعالم منParameters- نقم بإعطاء قيم للـ 3 التابعة لكائن األمر ، وذلك بعد تنظيفه منParametersخالل الخاصية

مستخدمةParameters ) فيما إذا كانت هناك أي Parametersإي .. ) � سابقا

كودUpdateCommand.Parameters.Clear)(UpdateCommand.Parameters.AddWithValue)"?", txtName.Text(UpdateCommand.Parameters.AddWithValue)"?", txtPhone.Text(UpdateCommand.Parameters.AddWithValue)"?", txtID.Text(

والتي سوف تقوم بتنفيذExecuteNonQuery- نطبق الطريقة 4استعالم تحديث الجدول ..

كودUpdateCommand.ExecuteNonQuery)(

ألننا انتهينا منه وحتى الUpdateCommand- نتخلص من كائن األمر 5 يستهلك جزاء من موارد النظام ، ثم نغلق االتصال بقاعدة البيانات

ونعرض رسالة بنجاح العملية ..

كودUpdateCommand.Dispose)(Conn.Close)(MsgBox)" OK ", MsgBoxStyle.Information(

� : في حدث النقر لـ نقوم بما يلي ..btnDeleteرابعا- نقوم بفتح االتصال ..1

كود

Page 11: ADO.Net - Arabic

Conn .Open

) باستخدامDeleteCommand- نقوم بتهيئة كائن أمر جديد ونسميه 2 جملة استعالم بنيوية تقوم بحذف السجل الحالي من قاعدة البيانات وذلك

كمعرف للسجل الذي نريد حذفه والتيIDاعتمادا على قيمة الحقل ) ونرمز له بالرمز ? ( ( ، وذلك منParameterسوف نقوم بتخزينها في

خالل الكود التالي ..

كودDim DeleteCommand As New OleDbCommandDeleteCommand.Connection = ConnDeleteCommand.CommandType = CommandType.TextDeleteCommand.CommandText = " DELETE FROM Information WHERE id = ?; "

الموجود في جملة االستعالم منParameter- نقم بإعطاء قيمة للـ 3 التابعة لكائن األمر ، وذلك بعد تنظيفه منParametersخالل الخاصية

مستخدمةParameters ) فيما إذا كانت هناك أي Parametersإي .. ) � سابقا

كودDeleteCommand.Parameters.Clear)(DeleteCommand.Parameters.AddWithValue)"?", txtID.Text(

والتي سوف تقوم بتنفيذExecuteNonQuery- نطبق الطريقة 4استعالم تحديث الجدول ..

كودDeleteCommand.ExecuteNonQuery)(

ألننا انتهينا منه وحتى الDeleteCommand- نتخلص من كائن األمر 5 يستهلك جزاء من موارد النظام ، ثم نغلق االتصال بقاعدة البيانات

ونعرض رسالة بنجاح العملية ..

كودDeleteCommand.Dispose)(Conn.Close)(MsgBox)" OK ", MsgBoxStyle.Information(

، استنادا للمثال األول ماذا لو أردنا ExecuteScalar : الطريقة 3مثال ، إذا فلنتابعInformationمعرفة عدد السجالت المخزنة في الجدول

شرح هذا المثال ..� : نضيف .btnCountId ، ونسميه Buttonأوال

� : في حدث النقر لـ نقوم بما يلي ..btnCountIdثانيا

Page 12: ADO.Net - Arabic

- نقوم بفتح االتصال بقاعدة البيانات ..1

كودConn.Open)(

) باستخدامCountIdCommand- نقوم بتهيئة كائن أمر جديد ونسميه 2 جملة استعالم بنيوية تقوم بإعطائنا عدد السجالت المخزنة في الجدول

Information.. وذلك من خالل الكود التالي ، )

كودDim CountIdCommand As New OleDbCommandCountIdCommand.Connection = ConnCountIdCommand.CommandType = CommandType.TextCountIdCommand.CommandText = "SELECT Count)id( AS CountID FROM Information;"

على سبيلCountId ونسميه String- نقم بالتصريح عن متغير من نوع 3 المثال ، وذلك كي نخزن فيه القيمة التي سوف يعود بها كائن األمر بعد أن

..ExecuteScalarنمرر له الخاصية

كودDim CountId As String = CountIdCommand.ExecuteScalar)(

CountId يبين لنا القيمة المخزنة في المتغير MsgBox- نقوم بعرض 4 ..Informationوهي هنا عدد السجالت الموجودة في الجدول

كودMsgBox)CountId, MsgBoxStyle.Information(

ألننا انتهينا منه وحتى الCountIdCommand- نتخلص من كائن األمر 5 يستهلك جزاء من موارد النظام ، ثم نغلق االتصال بقاعدة البيانات

ونعرض رسالة بنجاح العملية ..

كودInsertCommand.Dispose)(Conn.Close)(MsgBox)" OK ", MsgBoxStyle.Information(

، لم أحب أن ضيفه للكائنات الثالثة األولىTransactionالكائن الرابع : ألني أعتقد بأنه فرعي وليس أساسي ، و وضيفته أمنيه بحته ، حيث

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

بالكامل ، على سبيل المثال : في الحسابات البنكية ، عند سحب مبلغ من

Page 13: ADO.Net - Arabic

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

إلغاء هذه العملية بالكامل . وCommit هي الخصيتان )Transactionومن أهم خصائص الكائن

Rollback. ) تدل على نجاع العملية بدون مشاكل أو أيCommitحيث أن الخاصية

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

يجب أن نصرح عنه كمتغير كما فيTransactionولكي نهيئ الكائن الكود ...

كودDim MyTransaction As OleDbTransaction

التابعة لكائن االتصال ونسندهاBeginTransactionثم نستدعي الخاصية له ، كما يلي ..

كودMyTransaction = Conn.BeginTransaction

( الذي نريدInsertCommand، ثم نهيئ كائن األمر ) على سبيل المثال منه تحديث البيانات بإضافة سجل جديد ، وذلك باستدعاء الخاصية

Transaction التابعة له وإسناد الكائن Transaction.. له

كودInsertCommand.Transaction = MyTransaction

لكائن األمر نقوم بإستدعاءExecuteNonQueryوبعد تنفيذ الخاصية وذلك لتأكيد قبولTransaction التابعة للكائن Commitالخاصية

العملية ونجاحها ..

كودMyTransaction.Commit)(

التابعة للكائنRollbackوفي حالة وجود أي مشكلة نستدعي الخاصية Transaction... وذلك للقيام بإلغاء العملية

كودMyTransaction.Rollback )(

لذلك ننصح تعشيش كل العمليات التي يتوقع وجود مشاكل بها داخل دالة .Try...Catch…Finallyاكتشاف األخطاء

، بالرجوع للمثال الثاني ونريد تعديلTransactionالمثال الرابع : الكائن كي نضمنTransactionبيانات السجل الحالي ونريد أن نستخدم الكائن

Page 14: ADO.Net - Arabic

عدم حدوث أخطاء وأن كل البيانات المطلوبة قد تم تحديثها ، والتراجع عن التحديث بالكامل في حالة لم يتم تحديث حقل من الحقول . وللقيام

بذلك نتبع األتي .. نقوم بما يلي ..btnUpdateفي حدث النقر لـ

ونعطيه االسمTransaction- نقوم بالتصريح عن متغيرين ، األول كائن 1MyTransaction والثاني ، Commandونعطيه االسم

UpdateCommand...

كودDim MyTransaction As OleDbTransactionDim UpdateCommand As New OleDbCommand

) معTry...Catch…Finally- نقوم بتعشيش دالة اكتشاف األخطاء 2 قمنا بالتصريح عن متغير أسميناهCatchمالحظة أننا في جزئية الدالة

Filed من نوع OleDbExceptionوهو من الكائنات التابعة لفضاء ونستفيد منه في الحصول علىSystem.Data.OleDbاألسماء

معلومات عن سبب الخطأ عند حدوثه في مصدر البيانات . ( كما يلي ..

كودTryالعمليات التي نرغب في اصطياد أخطائها إن وجدت   '       Catch Filed As OleDbExceptionاألخطاء التي تم اصطيادها ، باإلضافة للتصحيح المناسب لها '       Finallyالعمليات التي يجب تنفيذها على كل حال 'End Try

مالحظة : في الجزء الذي يحتوي على العمليات التي نرغب في اصطياد نقوم بما يلي ..Tryأخطائها إن وجدت من دالة

- نقوم بفتح االتصال ..3

كودConn .Open

� من4 - استنادا لما تعلمناه في السطور السابقة نقوم بإعداد وتجهيز كال ) مع مالحظة أننا استخدمناCommand والكائن Transactionالكائن

لوحدهName لتحديث الحقل ExecuteNonQueryهذه المرة الخاصية ، مع تعمد كتابة خطأPhoneثم استخدمناها مرة� أخرى لتحديث الحقل وبالتحديد في الكلمة "Phoneفي جملة االستعالم التي نحدث بها الحقل

UPDATE والتي كتبناها "ABDATEوذلك حتى نتعرف على الطريقة ، "" التي سوف يتم بها اصطياد الخطأ وكيف سوف يتم تصحيحه ( ...

كود

Page 15: ADO.Net - Arabic

MyTransaction = Conn.BeginTransactionUpdateCommand.Connection = ConnUpdateCommand.Transaction = MyTransactionUpdateCommand.CommandType = CommandType.TextUpdateCommand.CommandText = "UPDATE Information set Name=? WHERE Id =?;"UpdateCommand.Parameters.Clear)(UpdateCommand.Parameters.AddWithValue)"?", txtName.Text(UpdateCommand.Parameters.AddWithValue)"?", txtID.Text(UpdateCommand.ExecuteNonQuery)(UpdateCommand.CommandText = "ABDATE Information set Phone=? WHERE Id =?;"UpdateCommand.Parameters.Clear)(UpdateCommand.Parameters.AddWithValue)"?", txtPhone.Text(UpdateCommand.Parameters.AddWithValue)"?", txtID.Text(UpdateCommand.ExecuteNonQuery)(

وذلكTransaction التابعة للكائن Commit- نقوم باستدعاء الخاصية 5لتأكيد قبول العملية ونجاحها مع عرض رسالة تفيد بنجاح العملية ..

كودMyTransaction.Commit)(MsgBox)" OK ", MsgBoxStyle.Information(

والذي يحتوي علىTry من دالة Catchمالحظة : في الجزء المسمى األخطاء التي تم اصطيادها ، باإلضافة للتصحيح المناسب لها نقوم بما

يلي .. وذلكTransaction التابعة للكائن Rollback- نستدعي الخاصية 6

للقيام بإلغاء العملية ، ثم نعرض رسالة نصية توضح لنا معلومات عنالخطأ الذي وقع أثناء تنفيذ البرنامج ...

كودMyTransaction.Rollback)(MsgBox)Filed.Message, MsgBoxStyle.Exclamation(

والذي يحتوي علىTry من دالة Finallyمالحظة : في الجزء المسمى العمليات التي يجب تنفيذها على كل حال ، نقوم بما يلي ..

ألننا انتهينا منه وحتى الUpdateCommand- نتخلص من كائن األمر 7يستهلك جزاء من موارد النظام ، ثم نغلق االتصال بقاعدة البيانات ..

كودUpdateCommand.Dispose)(Conn.Close)(

� في شرح هذا الكائن من درس قدمه األخ مالحظة : لقد استفدت كثيراkoao. لذلك أحب أن أشكره على ذلك

Page 16: ADO.Net - Arabic

� من الراحة ، لكي نستوعب هذه ** هنا ينتهي حديثنا اليوم ، ونأخذ قسطا الجرعة من المعلومات ونصحح أخطائها إن وجدت ، ونعلق على الغير

مفهوم منها ، و نكمل فيما بعد شرح ما تبقى من الدرس وذلك فيالمشاركات القادمة ..

مالحظة : موضوعنا القادم يعد متعة برمجة قواعد البيانات الحقيقية ، وهو ( ، والذي كما أسلفناConnectionless Orientedاالتصال المنفصل )

يعتبر األمثل في التعامل مع قواعد البيانات ، ويغنينا عما سواه . إال أننا Connectionكان ال بد لنا من تعلم كيفية التعامل مع االتصال المتصل )

Oriented، ألنه يحل لنا بعض اإلشكاالت البرمجية في بعض البرامج ) رغم إننا لم نتناول كل جوانبه ، ولكني أحب أن يعلم الجميع أنني أفرغت

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

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

أمثلة الجزأ الثاني من الدرس توجد في الملف المرفق ..

( :Connectionless Oriented* االتصال المنفصل )

� يعد الوضع المنفصل هو األمثل للتعامل مع قواعد البيانات ، وذلك نظرا لإلمكانات والكائنات المتنوعة التي تمكن المستخدم من أخذ نسخة من

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

ذلك عمل التطبيقات بكفاءة عاليه . وألن معظم مصادر البيانات تدعم� من االتصاالت المفتوحة ، فإن الوضع المنفصل استطاع أن � محدودا عددا

�ما حين نستخدم تطبيقات متصلة بقواعد يتجاوز هذه المشكلة ، السيالبيانات عبر شبكة اإلنترنت ...

وتتلخص فكرته في أن نقوم بإجراء اتصال بقاعدة البيانات ، وذلك كما ذكرنا في الدروس السابقة ،Connectionبواسطة كائن االتصال

وبعد قبول االتصال نقوم بأخذ نسخة من البيانات المخزنة في مصدر " ) مصدر البيانات هنا هو ملف قاعدة البياناتData Sourcesالبيانات "

SQL أو السيرفر بالنسبة لـ Microsoft Office Accessبالنسبة لـ Serverثم نقوم بتخزينها في الذاكرة ، وذلك من خالل كائن يكون ، )

) مجموعة البيانات ( ، ولكيDataSetبمثابة مستودع للبيانات ويسمى DataAdapterتتم هذه العملية يحتاج هذا الكائن إلى كائن أخر يسمى

Page 17: ADO.Net - Arabic

"DataSet) موف�ق البيانات ( يكون بمثابة وسيط بين مجموعة البيانات " بعمليةDataAdapter" ، حيث يقوم Data Sourcesومصادر البيانات "

فتح االتصال بقاعدة البيانات و استيراد وتصدير البيانات من و إلى مصدرها ، فإنها تصبح منفصلة عنDataSetاألساسي ، وبعد تخزين البيانات في

�DataAdapterمصدر البيانات ، الن الكائن يقوم بشكل تلقائي أيضا بقطع االتصال بقاعدة البيانات ، وهذا االنفصال واالستقالل هو السبب في

تسمية هذه الطريقة باالتصال المنفصل أو الوضع المنفصل ، وهو السرفي تفوقه على الوضع المتصل ، ألنه يتغلب على جمع عيوبه ومشاكله .

ومن ذلك نستطيع أن نقول أن الكائنات األساسية في الوضع المنفصل .Connection ، DataSet ، DataAdapterهي :

� كائنات أخرى ليست فرعية ولكنها خدمية إن صح التعبير ،على وهناك أيضا ، DataTable ، DataRow ، DataColumnسبيل المثال "

DataRelation ، OleDbCommandBuilder ، BindingManagerBase ، CurrencyManager ، BindingSource"

،

ويأتي دورها في الغالب بعد وصول البيانات ) الجداول ( القادمة منÅناقش بعضهاDataSetمصادر البيانات إلى ) مجموعة البيانات ( . وسن

) أو كلها إذا وجدنا الوقت الكافي لذلك ( وما يهمنا منها بإيجاز غير مخلإن شاء الله ..

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

األمور حين نصل إلى الجزء العملي من الدرس .- - - - - - - - - - - - - - - - - - - - - - -

:-Connection - الكائن 1لقد تحدثنا عنه في الدروس السابقة بما فيه الكفاية .

2 – DataSet-: بأنها مستودع أو ذاكرة وسيطةDatasetيمكن تعرف مجموعة البيانات

لتخزين البيانات التي تم إحضارها من مصادر البيانات ، ويريد أن يستعملهاالتطبيق .

فيADOمن كان قد برمج قواعد البيانات باستخدام اإلصدار السابق من VisualBasic6 الكائن � حيث يعتبر نقطةRecordset فهو يعرف تماما

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

في اإلصدار الجديدDataSetاستعالم بنيوية ( واحد . بينما نجد أن الكائن يمكنه تمثيل النتائج المتولدة عن عدة جداول و تتبعADO.NETمن

Page 18: ADO.Net - Arabic

العالقات بين هذه الجداول ، أو تمثيل النتائج المتولدة عن استفسارات يشكل جدولRecordsetعديدة . وبذلك نستطيع أن نقول أنه إذا كان

يشكل قاعدة بيانات كاملة تجلس فيDataSetقاعدة بيانات ، فإن الذاكرة . ولعل ما في هذه النبذة ، ما يعطي القارئ تصور عام عن الكائن

DataSet و يزيل الجدل حول ، Recordset و DataSet. وأيهما أفضل

:DataSetوأالن سون نتطرق لبعض خصائص

:Clear* الخاصية ، بينما تبقيDataSetتزيل هذه الخاصية كل البيانات من جميع جداول ...DataSetتعريفات الجداول وأي تقييدات معرفه من قبل

كودMyDs.Clear

كماDataSetفإذا أردنا إزالة الجداول والتقييدات ، نقوم بإعادة إنشاء في الكود التالي ..

كودMyDs = New DataSet

:HasChangesالخاصية يتتبع فيما إذا كان هناك أي تغييرات قد أجريت على بياناته ،DataSetإن

ويمكن استدعاؤها بكل بساطه من خالل الكود التالي ..

كودMyDs.HasChanges

إذا كانت البيانات قد حدثت إما لتغيير أوtrueوتعيد هذه الخاصية القيمة ،DataSetإضافة أو حذف ، فإذا حمل برنامج ما بشكل أولي بيانات إلى �ر بعد وستعيد هذه الخاصية عندئذ القيمة Falseفإن البيانات لم تغي

ÅحÉدÈث المستخدم أي بيانات للجداول فإن هذه الخاصية سوف تعيد وعندما ي . وإذا قام المستخدم بحفظ بياناته المحدثة ، فإنها تعيدtrueالقيمة من جديد ..Falseالقيمة

فلنتأمل هذا الكود ..

كود

Page 19: ADO.Net - Arabic

   If MyDS.HasChanges = True Then. DataSet  نقوم بكتابة أي إجراء في حالة إذا كان هناك أي تغييرات قد أجريت على الـ '         Else. DataSet نقوم بكتابة أي إجراء في حالة إذا لم يكن هناك أي تغييرات قد أجريت على الـ '     End If

،DataRowStateويمكن أن تأخذ هذه الخاصية وسيط اختياري يسمى يشير إلى نوع التغييرات التي قد حدثت ، حيث يمكن استخدام هذه

الطريقة لرؤية فيما إذا كانت هناك سجالت قد أضيفت ، أو عدلت ، أو حذفت ، أو لم يقع عليها أي تغيير ، وذلك من خالل القيم التي يحملها هذا

الوسيط وهي على النحو التالي ..

-Added ويشير إلى الصفوف التي أضيفت إلى الـ : DataSet. -Deleted ويشير إلى الصفوف التي قد حذفت من الـ : DataSet. -Modifiedويشير إلى الصفوف التي قد غيرت قيم بياناتها من الـ :

DataSet. -Unchanged ويشير إلى أن الصفوف لم تتغير من الـ : DataSet.

ولكي يتضح الشرح نتأمل هذا الكود ...

كودIf MyDataSet.HasChanges)DataRowState.Added( Then .نقوم بكتابة أي إجراء في حالة إذا كان هناك صفوف جديدة قد أضيفت '      ElseIf MyDataSet.HasChanges)DataRowState.Deleted( Then . نقوم بكتابة أي إجراء في حالة إذا كان هناك صفوف قد حذفت '      ElseIf MyDataSet.HasChanges)DataRowState.Modified( Then نقوم بكتابة أي إجراء في حالة إذا كان هناك صفوف قد تغيرت قيمها '      ElseIf MyDataSet.HasChanges)DataRowState.Unchanged( Then. نقوم بكتابة أي إجراء في حالة إذا لم يحدث أي تغيير على الصفوف '      End If

:AcceptChangesالخاصية الذي تم التعديل لبياناته ،DataSetتقوم هذه الخاصية بإعادة وضع الـ

� االستدعاءات المستقبلية للخاصية ليشير إلى أن البيانات لم تعدل . جاعالHasChanges تعيد القيمة Falseإدراك أن � . إنه من الهام جدا

AcceptChangesال تقوم بالواقع بتحديث قاعدة البيانات ، إنها فقط المعدل . وبشكل نموذجي فإن أي برنامج سيقومDataSetتعيد وضع الـ

بتخزين أية تغييرات إلى قاعدة البيانات ، ومن ثم يستدعيAcceptChanges. بعد ذلك مباشرة

كود  كود تصدير البيانات المحدثة من مجموعة البيانات إلى مصدر البيانات باستخدام موف�ق البيانات 'MyDs.AcceptChanges

Page 20: ADO.Net - Arabic

:RejectChangesالخاصية تقوم هذه الخاصية بإلغاء أية تغييرات قد أجريت على البيانات في الـ

DataSetمنذ تحميلها ، أو منذ أخر استدعاء لها ، بمعنى أنها تلغي أية � ، وتعيد وضع � حديثا � حذفت أيضا � ، وتستعيد أسطرا أسطر مضافة حديثا

األسطر المعدلة إلى قيمتها السابقة ، كما أنها تقوم بإعادة وضع الـDataSet. الذي تم التعديل لبياناته ، ليشير إلى أن البيانات لم تعدل

� االستدعاءات المستقبلية للخاصية تعيد القيمةHasChangesجاعالFalse.

كودMyDs.RejectChanges

مالحظة : بإزالة المعلومات حول الحالة السابقةAcceptChangesتقوم الخاصية

الستعادة آخر قيمRejectChangesللبيانات ، وبالتالي ال يمكن استخدام سيؤدي إلى استعادة البياناتRejectChangesللبيانات ، هذا يعني أن

.AcceptChangesبالحالة التي كانت عليها بعد آخر استدعاء للخاصية

:GetChangesالخاصية جديد بنفس بنية الكائنDataSetتساعدنا هذه الخاصية في إنشاء كائن

األصلي ، ولكنه يحتوي فقط على سجالت تمثل التغييرات التي حدثت� وسيط إختياري ) الذي تحدثنا عنهDataRowStateللبيانات ، وله أيضا

فيما إذا يتوجب عليهاGetChanges ( يخبر HasChangesفي الخاصية إحضار السجالت التي أضيفت أو عدلت أو حذفت أو تركت دون تغيير .

الختيار أكثر من نوع واحد منDataRowStateوباإلمكان جمع قيم .DataSetالتغييرات التي حدثت للبيانات داخل الكائن

ولها استخدامات كثيرة منها :� ، نحن في الوضع المنفصل نستخدم الكائن 1 DataAdapter- قلنا سابقا

إلى مصدر قاعدةDataSetإلعادة تخزين التغييرات الموجودة في التابعة للكائنUpdateالبيانات . وذلك يتم من خالل الخاصية

DataAdapterالذي سوف نتحدث عنه فيما بعد ، ما يهمنا هنا هو أن � تلو اآلخر .DataSetهذه الخاصية تبحث خالل عن تغييرات وتخزنها واحدا

ويكون تخزين التغييرات أسرع إذا جÅمعت في مجموعات حسب نوعها ،� أفضل ، إذا حفظتUpdateوبكلمات أخرى فإن الخاصية ستعطي إنجازا

� كل المحذوفات . � ، ثم بعد ذلك كل اإلضافات وأخيرا كل التعديالت أوال� يحتاج برنامج ما تخزين تغييرات في ترتيب معين ، ليفي2 - أحيانا

بمتطلبات التقييدات العالئقية لجداول قاعدة البيانات .

� هذه األمثلة .. ولكي نفهم طريقة هذه الخاصية ، فلنتابع سويا

: ) إخبار المستخدم عن عدد السجالت الجديدة (1مثال جديد ، ثم نختبر فيماDataSetفي هذا المثال نقوم بالتصريح عن كائن

Page 21: ADO.Net - Arabic

إذا كان الكائن األصلي يحتوي على أي تغييرات عليه ، وفي حالة وجود أي لتأهيل الكائن الجديد بنفس بنيةGetChangesتغيير نستخدم الخاصية

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

كود   Dim ds_added As New DataSet   If MyDS.HasChanges Then       ds_added = MyDS.GetChanges)DataRowState.Added(       If )Not )ds_added( Is Nothing( Then           MsgBox)ds_added.Tables)0(.Rows.Count & " Records Added "(       End IfEnd If

، Deleted ، Modifiedويمكن قياس هذا المثال على باقي القيم )Unchanged)

الختيار أكثر من نوع واحد منDataRowState : )جمع قيم 2مثال (DataSetالتغييرات التي حدثت للبيانات داخل الكائن

جديد ، ثم نختبر فيماDataSetفي هذا المثال نقوم بالتصريح عن كائن إذا كان الكائن األصلي يحتوي على أي تغييرات عليه ، وفي حالة وجود أي

لتأهيل الكائن الجديد بنفس بنيةGetChangesتغيير نستخدم الخاصية الكائن األصلي ، ويحتوي فقط على السجالت التي أضيفت أو حذفت ،

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

المستخدم بذلك ..

كود   Dim ds_AddedOrDeleted As New DataSet   If MyDS.HasChanges Then       ds_AddedOrDeleted = MyDS.GetChanges)DataRowState.Added Or DataRowState.Deleted(       If )Not )ds_AddedOrDeleted( Is Nothing( Then           MsgBox)ds_AddedOrDeleted.Tables)0(.Rows.Count & " Records Added or Deleted "(       End IfEnd If

: ) تحديث التغييرات حسب نوعها ، لتخزين البيانات بشكل3مثال أسرع (

حتى تتضحGetChangesمالحظة : نرجو التركيز على الجزء الخاص بـ الصورة الكاملة في أذهاننا من خال متابعة باقي الدروس ، بعدها يمكننا

فهم باقي تفاصيل الكود الغامضة في هذا الوقت .

Page 22: ADO.Net - Arabic

جديدين ، وكائن أخرDataSetفي هذا المثال نقوم بالتصريح عن كائنين .CommandBuilderيسمى باني األوامر

يقوم ببناء األوامر الخاصة بتحديثCommandBuilderمالحظة : الكائن DataAdapterالبيانات من تعديل وإضافة وحذف ، والتي يحتاجها الكائن

في عملية التحديث .

بـالكائنCommandBuilderوخالل ذلك التصريح نقوم بربط كائن DataAdapterثم نقوم بإيقاف التحديث للبيانات الموجودة في الـ ،

DataSetوقبول التحديثات الحالية من أجل حفظها ونقلها من الـ DataSet إلى مصدر البيانات ، ثم نختبر فيما إذا كان الكائن Dataset

األصلي يحتوي على أي تغييرات عليه ، وفي حالة وجود أي تغيير نستخدم بنفس بنيةds_Changes لتأهيل الكائن الجديد GetChangesالخاصية

� الخاصية لتأهيل الكائنGetChangesالكائن األصلي ، و نستخدم أيضا ، وجعله يحتويds_Changes بنفس بنية الكائن ds_subsetالجديد

فقط على السجالت التي عدلت ، وقبل حفظ البيانات ونقلها من الـDataSet إلى مصدر البيانات باستخدام الخاصية Updateالتابعة للكائن

MyDataAdapter نختبر الكائن الجديد ، ds_subsetلنتأكد من احتوائه على بيانات ، وفي حالة وجود بيانات نقوم بعملية النقل . ثم نكرر الجزء

األخير من الشرح بالنسبة لكل من اإلضافة والحذف ، وفي األخير الذي تمDataSet إلعادة وضع الـ AcceptChangesنستدعي الخاصية

� االستدعاءات المستقبلية للخاصية HasChangesالتعديل لبياناته ، جاعال..Falseتعيد القيمة

كود   Dim ds_Changes As New DataSet   Dim ds_subset As New DataSet   Dim MyCB As New OleDbCommandBuilder)MyDataAdapter(   Me.BindingContext)MyDS, "Information"(.EndCurrentEdit)(   If MyDS.HasChanges Then      ds_Changes = MyDS.GetChanges      ds_subset = ds_Changes.GetChanges)DataRowState.Modified(      If )Not )ds_subset( Is Nothing( Then MyDataAdapter.Update)ds_subset.Tables)0((      ds_subset = ds_Changes.GetChanges)DataRowState.Added(      If )Not )ds_subset( Is Nothing( Then MyDataAdapter.Update)ds_subset.Tables)0((      ds_subset = ds_Changes.GetChanges)DataRowState.Deleted(      If )Not )ds_subset( Is Nothing( Then MyDataAdapter.Update)ds_subset.Tables)0((      MyDS.AcceptChanges)(End If

:HasErrorsالخاصية � أدخل القيمة " Integer " في حقل من النوع ADOنفرض أن مستخدما

Page 23: ADO.Net - Arabic

ÅعلÈم هذا الحقل في هذا السجل بالذات برسالة عندئذ يمكن للبرنامج أن ي� وقبل أن يقوم البرنامج بتحديث قاعدة البيانات ، فإنه يمكن خطأ . الحقا

لتحديد فيما إذا كانتDataSet الخاصة بـ HasErrorsاستخدام خاصية البيانات تملك أخطاء يتوجب على المستخدم إصالحها .

ربما يرى البعض أنه من األفضل أن يخبر البرنامج المستخدم عن وجود أخطاء في البيانات المدخلة مباشرة ، مثل استخدام األداة

ErrorProvider. يكون من المفيد تأجيل معالجة األخطاء � ، ولكن أحيانا كمثال : ربما كانت قيمة أحد الحقول تعتمد على قيمة حقل آخر لم تدخل

بعد ، في هذه الحالة فإن البرنامج يجب عليه االنتظار حتى تدخل كالالقيمتين ، قبل أن يقرر فيما إذا كانت هناك مشكلة ما .

إذا كانت البيانات تملك أخطاء يتوجبtrueوتعيد هذه الخاصية القيمة إذا لم توجد أخطاء فيFalseعلى المستخدم إصالحها ، وبالمقابل القيمة

البيانات .مثال :

كودIf MyDataSet.HasErrors = True Thenأدخل الكود الخاص بتصحيح الخطأ '   Elseأدخل الكود الخاص بحفظ البيانات المدخلة '   End If

:Tablesالخاصية ومنهاDataSetنصل من خالل هذه الخاصية إلى الجداول المخزنة في

إلى الصفوف واألعمدة الموجودة في هذه الجداول ، بل و إلى القيمالمخزنة في أي خلية من الخاليا الموجودة في الجدول .

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

الوضوح ( كما في المثال التالي ..

كودMyDS.Tables)"Information"(

والطريقة الثانية هي أن نرمز للجدول من خالل رقمه داخل الكائنDataSet أن رقم أول جدول داخل الكائن � ،0 هو الرقم DataSet علما

كما في المثال التالي ..

كودMyDS.Tables)0(

� التحكم في صفوف الجدول المحدد من خالل الخاصية Rowsويمكن أيضا التابعة لها ، وكل ذلك يتم بشكل مباشر بدونItemالتابعة له ، والخاصية

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

Page 24: ADO.Net - Arabic

بشكل أفضل ..

مالحظة : ما سوف يتم شرحه في السطور التالية من باب العلم أوBindingManagerBaseبالشيء ، وإال فإن الكائنات الخدمية )

CurrencyManager أو BindingSourceتغنينا عن ذلك وبشكل ) � وجميل . مختصر جدا

لمعرفة عدد سجالت أحد الجداول نقوم بكتابة ما يلي ..

كودMyDS.Tables)"Information"(.Rows.Count

لمعرفة القيمة المخزنة في الخلية الموجودة في الصف األول والعموداألول ، وعرضها في مربع رسالة ، نقوم بكتابة ما يلي ..

كودMsgBox)MyDS.Tables)"Information"(.Rows)0(.Item)0((

كما نستطيع أعادة كتابة الكود السابق ، بحيث نحدد فيه عمود محدد ،بكتابة ما يلي ..

كودMsgBox)MyDS.Tables)"Information"(.Rows)0(.Item)"Name"((

،Nameلتغير قيمة الخلية الموجودة في الصف األول والعمود المسمى نقوم بكتابة ما يلي ..

كودMyDS.Tables)"Information"(.Rows)0(.Item)"Name"(="Yaser"

لحذف السجل ) الصف ( األول من الجدول ، نقوم بكتابة ما يلي ..

كودMyDS.Tables)"Information"(.Rows)0(.Delete)(

للتراجع عن التغيرات التي قمنا بها من تعديل وحذف ، نقوم بكتابة مايلي ..

كودMyDS.Tables)"Information"(.Rows)0(.RejectChanges)(

إلضافة سجل جديد ، نخزن البيانات التي نريدها في مصفوفة ، ونسندها كما في الكود التالي ..Addللخاصية

Page 25: ADO.Net - Arabic

كود   Dim MyData)( As String = {"Yaser", "32", "Gizan"}MyDS.Tables)"Information"(.Rows.Add)MyData(

، وتأهيله بصفDataRowويمكن تطوير الكود السابق باستخدام الكائن ،Itemجديد في الجدول المحدد ، وإدخال القيم فيه من خالل الخاصية

التابعة لصفوف الجدول ،Add إلى للخاصية DataRowثم نسند الكائن كما في الكود التالي ..

كود   Dim MyDR As DataRow = MyDS.Tables)"Information"(.NewRow   MyDR.Item)"name"( = "yaser mohamed"   MyDR.Item)"age"( = "32"   MyDR.Item)"City"( = "Gizan"MyDS.Tables)"Information"(.Rows.Add)mydr(

سنكتفي بذلك القدر ، وننتقل إلى التنقل بين السجالت ..

لمعرفة رقم موقع السجل الحالي وعرضه في مربع رسالة ، نكتب ما يلي..

كودMsgBox)Me.BindingContext)MyDS, "Information"(.Position(

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

كودMsgBox)Me.BindingContext)MyDS, "Information"(.Count(

ولالنتقال للسجل األول في الجدول نكتب ما يلي ..

كودMe.BindingContext)MyDS, "Information"(.Position = 0

ولالنتقال للسجل األخير في الجدول نكتب ما يلي ..

كود   Me.BindingContext)MyDS, "Information"(.Position = Me.BindingContext)MyDS, "Information"(.Count -1

ولالنتقال للسجل التالي في الجدول نكتب ما يلي ..

كود   Dim MyPosition As Integer = Me.BindingContext)MyDS, "Information"(.PositionMe.BindingContext)MyDS, "Information"(.Position = MyPosition +1

Page 26: ADO.Net - Arabic

ولالنتقال للسجل السابق في الجدول نكتب ما يلي ..

كود   Dim MyPosition As Integer = Me.BindingContext)MyDS, "Information"(.PositionMe.BindingContext)MyDS, "Information"(.Position = MyPosition -1

** هنا ينتهي حديثنا اليوم ، فما أصبنا من صواب فمن الله وتوفيقه ، وما أصبنا من خطأ فمن أنفسنا والشيطان ، لذلك من وجد أي أخطاء

.. � فليصححها لنا مشكورا� من الراحة ، لكي نستوعب هذه الجرعة من المعلومات ولنأخذ قسطا

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

..DataAdapterالله هو الكائن

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

DataSet..

) الدمج ( :Mergeالخاصية

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

DataTable أو مصفوفة البيانات DataRowجÉدمÅويملك الكائن الم ، األصلية ، كمثال : إذا كان الكائنDataSetعادة� بنية مشابهة للكائن

أخرى ، فإنه من الممكن أن يملكDataSetالجديد هو عبارة عن األولى ) األصلية ( .DataSetالجداول نفسها التي في

وطريقة استخدامها هي كالتالي : أصلية ، ومثالDataSet فرعية داخل DataSet- عبارة عن دمج 1

ذلك ..

كودDim MyDS As DataSetDim SubSet_DS As DataSet

MyDS.Merge)dataSet(

Page 27: ADO.Net - Arabic

أصلية ، ومثال ذلك ..DataSet داخل DataTable- عبارة عن دمج 2

كودDim MyDS As DataSetDim MyTable As DataTable

MyDS.Merge)MyTable(

أصلية ، ومثال ذلك ..DataSet داخل DataRow- عبارة عن دمج 3

كودDim MyDS As DataSetDim Rows As DataRow)(

MyDS.Merge)Rows(

Ôدة بواسطة الخاصيةDataSetومن المعلوم أن الكائن المولGetChange متوافقة مع DataSetاألصلية ) الحتوائها على نفس

التكوين و البنية ( . حيث يمكن للبرنامج على سبيل المثال استخدام فرعي والمحتويDataSet للحصول على كائن GetChangeالخاصية

فقط على التغييرات ) أو اإلضافات أو المحذوفات كما ذكرنا في الدروس السابقة ( ، ويمكنه بعد ذلك تثبيت التغييرات مع إمكانية تعديل بعض قيم

البيانات ، ثم يحفظ التغييرات في قاعدة البيانات . وبعد انتهاء البرنامج من Mergeتحديث قاعدة البيانات ، فإن البرنامج يمكنه من خالل الخاصية

� إياها إلى األصلية ، وبالتالي فإنها ستكونDataSetدمج التغييرات معيدا متزامنة مع قاعدة البيانات . ويفرض علينا ذلك طبيعة البرنامج الذي

� في حالة احتوائه على تقيدات عالئقية أو تقيدات نتعامل معه ، وخصوصا أمنية معينه يحتاجها المبرمج ، ولكي تتضح الصورة فلنتأمل المثال التالي )

يحتاج هذا المثال إلى قراءة و فهم الدروس السابقة ( ..

كودDim ds_Changes As New DataSet   Dim ds_subset As New DataSet   Dim MyCB As New OleDbCommandBuilder)MyDataAdapter(   Me.BindingContext)MyDS, "Information"(.EndCurrentEdit)(     If MyDS.HasChanges Then         ds_Changes = MyDS.GetChanges         ds_subset = ds_Changes.GetChanges)DataRowState.Modified(         If )Not )ds_subset( Is Nothing( Then             MyDA.Update)ds_subset.Tables)"Information"((             MyDS.Merge)ds_subset(         End If         ds_subset = ds_Changes.GetChanges)DataRowState.Added(         If )Not )ds_subset( Is Nothing( Then

Page 28: ADO.Net - Arabic

             MyDA.Update)ds_subset.Tables)"Information"((             MyDS.Merge)ds_subset(         End If         ds_subset = ds_Changes.GetChanges)DataRowState.Deleted(         If )Not )ds_subset( Is Nothing( Then             MyDA.Update)ds_subset.Tables)"Information"((             MyDS.Merge)ds_subset(         End If         MyDS.AcceptChanges)(  End If

تأخذ وسيطين اختياريين غيرMergeو من باب العلم بالشيء ، الخاصية إلزاميين ، يخبرانها بكيفية الدمج ، الوسيط األول هو قيمة منطقية )

Boolean وتحمل إما القيمة ) True أو القيمة Falseوتخبر الخاصية ، Merge حافظ على التغييرات فيÅ األصليDataSet فيما إذا يجب أن ت

، أم ال وذلك من خالل اختيار القيمةTrueوذلك من خالل اختيار القيمة Falseالوسيط الثاني ويحمل أربع قيم ، من خاللها يخبر الخاصية .

Mergeماذا يتوجب عليها فعله عند فقدان جدول أو عمود ما في الـ DataSet الفرعية أو في الـ DataSetاألصلية ، حيث أنه عند استدعاء األصليDataSet تقوم بالمقارنة بين مخططين الـ Mergeالخاصية

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

و ملخص هذه القيم ، مع طريقة استخدامها :-

:MissingSchemaAction.Add- القيمة 1 تضيف الجدول أو العمود الجديد .Mergeتجعل الخاصية

كودMyDS.Merge)ds_subset, False, MissingSchemaAction.Add(

:MissingSchemaAction.AddWithKey- القيمة 2 تضيف أعمدة جديدة ومعلومات عن المفتاحMergeتجعل الخصية

الرئيسي عند الضرورة .

كودMyDS.Merge)ds_subset, False, MissingSchemaAction.AddWithKey(

:MissingSchemaAction.Error- القيمة 3 تعلن عن أخطاء ، إذا لم تجد مطابقة البياناتMergeتجعل الخاصية

األصلية .DataSetالواردة مع بنية الـ

Page 29: ADO.Net - Arabic

كودMyDS.Merge)ds_subset, False,  MissingSchemaAction.Error(

:MissingSchemaAction.Ignore- القيمة 4 تتجاهل البيانات الجديدة إذا لم تتطابق مع الـMergeتجعل الخاصية

DataSet. األصلية

كودMyDS.Merge)ds_subset, False, MissingSchemaAction.Ignore(

:Cloneالخاصية DataSet األصلية إلى الـ DataSetتنسخ هذه الخاصية نفس بنية الـ

الجديدة ، بحيث تمتلك نفس الجداول والتقيدات ، وطريقة استخدامها ..

كودDim MyDS As New DataSet   Dim ds_subset As New DataSet

ds_subset = MyDS.Clone

:Copyالخاصية األصلية إلى الـDataSetتنسخ هذه الخاصية نفس بنية و بيانات الـ

DataSetالجديدة ، بحيث تمتلك نفس الجداول والتقيدات والبيانات � ، وبالتالي فإن ولكنها تتضمن البيانات ،Clone مشابهة لـ Copyأيضا

وطريقة استخدامها ..

كودDim MyDS As New DataSet   Dim ds_subset As New DataSet

ds_subset = MyDS.Copy

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

------------------------------------------------------------------------------------------------------------------

Page 30: ADO.Net - Arabic

وبه أبدا وأستعين ، وأختم بالصالة والسالم على خاتم األنبياء والمرسليننبينا محمد وعلى آله وصحبه أجمعين ، أما بعد ..

============= :DataAdapter - الكائن 3

في الدروس السابقة وضحنا العمل الذي يقوم به هذا الكائن ، حيث قلنا " ومصادرDataSetحينها أنه " بمثابة وسيط بين مجموعة البيانات "

بعملية فتحDataAdapter" ، حيث يقوم Data Sourcesالبيانات " االتصال بقاعدة البيانات و استيراد وتصدير البيانات من و إلى مصدرها

، فإنها تصبح منفصلة عنDataSetاألساسي ، وبعد تخزين البيانات في �DataAdapterمصدر البيانات ، الن الكائن يقوم بشكل تلقائي أيضا

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

يستخدم هذا الكائن كائنان صديقان تعرفنا عليهما فيما سبق ، وهما : إلدارة اتصاله بقاعدة البيانات ) من فتحOleDbConnectionالكائن

إلدارةOleDbCommandاالتصال و غلق االتصال ( ، و الكائن البنيوية التي يجب تنفيذها ) من تحديد أو إضافة أو تعديلSQLاستعالمات

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

OleDbConnectionكيف يتم إنشاء مالئم بيانات ، واستخدام الكائن إلدارة اتصاله بقاعدة البيانات ، وكذلك استخدام الكائن

OleDbCommand إلدارة استعالم SQLوالذي يقوم بتحديد مجموعة من الحقول المتوفرة في إحدى جداول قاعدة البيانات التي تم االتصال بها

وهيDataAdapter، وكذلك سوف نستخدم إحدى خصائص الكائن SelectCommandولكنا لن نزعج أنفسنا بها هنا ، وسوف نشرحها

بالتفصيل في وقت الحق ، فقط نحتاج إلى القليل من التركيز لتأمل الكودالتالي ..

كود' Create the ConnectionString.Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(' Create the SelectCommand.Dim selectCommand As OleDbCommand = New OleDbCommand)"SELECT * FROM Information"(        Dim instance_adapter As New OleDbDataAdapter)(instance_adapter.SelectCommand = selectCommandinstance_adapter.SelectCommand.Connection = selectConnection

ويمكن اختصار الكود السابق ليصبح كما يلي ..

كود

Page 31: ADO.Net - Arabic

' Create the ConnectionString.Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(' Create the SelectCommand.Dim selectCommand As OleDbCommand = New OleDbCommand)"SELECT * FROM Information", _       selectConnection(Dim instance_adapter As New OleDbDataAdapter)(instance_adapter.SelectCommand = selectCommand

ويمكن اختصار الكود السبق أكثر من ذلك ليصبح كما يلي ..

كودDim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;Jet OLEDB:Database Password=ado.net;"(Dim selectCommandText As String = "SELECT * FROM Information"Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(

ويمكن اختصار الكود السبق أكثر من ذلك ليصبح كما يلي ..

كودDim instance_adapter As New OleDbDataAdapter)"SELECT * FROM Information" _, "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Note.mdb;" _& "User Id=admin;Jet OLEDB:Database Password=ado.net;"(

بالعديد من الخصائص ، ومن أهمها :-DataAdapterويتمتع هذا الكائن :Fill* الخاصية

حيث تنقل البيانات من قاعدة البيانات )مصدرها األساسي ( إلىDataSet أوDataTableوبعبارة أخرى القيام بعملية االستيراد . والكود ،

وتجهيزه ، واستخدامDataAdapterالتالي يبين كيف يتم إنشاء الكائن بالجدول المحدد في جملة االستعالم ،DataSet لتعبئة الـ Fillالخاصية

ومن بعد ذلك نعرض مربع رسالة تخبرنا بعدد السجالت المتوفرة في للتو ..DataSetالجدول الذي تم تخزينه في

كودDim selectCommandText As String = "SELECT * FROM Information"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText,

Page 32: ADO.Net - Arabic

selectConnection(Dim MyDs As New DataSetinstance_adapter.Fill)MyDs(MsgBox)MyDs.Tables)0(.Rows.Count, MsgBoxStyle.Information(

تأخذ الكثير من المتغيرات ) البارامترات ( ،Fillفي الحقيقة الخاصية ومن خالله نستطيع أن نضع اسمsrcTableسنتحدث عن أهمها ، وهو

وذلك من أجل الحصول علىDataSetللجدول الذي نريد تخزينه في الـ اسم ذو معنى أوضح ، وبدون هذا المتغير سوف يأخذ هذا الجدول االسم "

Tableوفي مثالنا السابق نستطيع استبدال السطر التاسع بالكود ، " " ..Demoالتالي إلعطاء الجدول اسم "

كودinstance_adapter.Fill)ds, "Demo"(

، نكتبDataSetولكي نتأكد من اسم الجدول الذي قمنا بتخزينه في الـ الكود التالي لعرض مربع رسالة تخبرنا باسم الجدول ..

كودMsgBox)ds.Tables)0(.TableName(

مالحظة :- الصورة الكاملة للمتغيرات ) البارامترات ( التي تأخذها ..Fillالخاصية

كودinstance_adapter.Fill)MyDataSet As DataSet, startRecord  As Integer, maxRecords As Integer, srcTable As String(

حيث أن : التي نريد تخزينDataset يشير إلى الـ MyDataSet- البارامتر 1

الجدول بها . يشير إلى رقم السجل الذي نريد أن نبدأ بهstartRecord- البارامتر 2

في تحميل البيانات ) يجب أن نعلم أن هذا الرقم يبدأ بالرقم صفر ويدل على السجل األول ( من الجدول الذي نريد نسخ بياناته وتكوينه في الـ

Dataset. يشير إلى رقم السجل الذي نريد أن ننتهيmaxRecords- البارامتر 3

عنده في تحميل البيانات من الجدول الذي نريد نسخ بياناته وتكوينه في .Datasetالـ يشير إلى االسم المقترح للجدول الذي نريدsrcTable- البارامتر 4

.Datasetتكوينه في الـ مثال :-

في المثال التالي لدينا جدول يحتوي على مجموعة من السجالت عددها

Page 33: ADO.Net - Arabic

،DataSet سجل ، ونريد أن نخزن تكوين وبيانات هذا الجدول في الـ 15� اختيار مجموعة محدده من السجالت ، على أن نبدأ من السجل ونريد أيضا

( وننتهي إلى4الخامس ) بالطبع ترتيبه داخل السجالت يحمل الرقم ( ، وبعد9السجل العاشر ) بالطبع ترتيبه داخل السجالت يحمل الرقم

" ، وفي األخير نعرضDemoذلك نريد أن نعطي هذا الجدول االسم " مربع رسالة تخبرنا بعدد السجالت في الجدول الذي تم تخزينه للتو ،

وقيمة السجل األول في العمود األول من الجدول ..

كودDim selectCommandText As String = "SELECT * FROM Information order by name"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.Fill)ds, 4, 9, "Demo"(Dim strMsg As String = String.Format)"Count of Records In The {0} Table = {1}.{2}The " _& "First Value In The second Column Is : {3} .", _ds.Tables)0(.TableName, ds.Tables)0(.Rows.Count, vbNewLine, _ ds.Tables)0(.Rows)0(.Item)0(MsgBox)strMsg, MsgBoxStyle.Information(

)) يمكن تغيير األرقام ومشاهدة النتائج المختلفة ((

:TableMappings* الخاصية بياناته من قاعدة البيانات بواسطة جملةDataAdapterعندما يختار

ضمن جدول يحملDataSetاالستعالم للمرة األولى ، فإنه يخزنها في الـ بشكل تلقائي ، وأي تحميل آخر للبيانات في الـTableاسم افتراضي

DataSet فإنها سوف تخزن ضمن جداول تحمل اسم table1 ، Table2 ، ... وهكذا ، و هذا االسم كما يبدو ال يدل على اسم ذو معنى واضح ،

تحويله إلى اسم ذو معنى أوضح ،TableMappingsونستطيع من خالل ولعل التمثيل الذي في الصورة التالية يوضح الفكرة ...

Page 34: ADO.Net - Arabic

Add للخاصية Stringولكي نقوم بذلك نحتاج إلى تمرير متغيرين من نوع وهو اسمSourceTable ، األول TableMappingsالتابعة للخاصية

وهو االسم الذي نريدهDataSetTableالجدول االفتراضي ، والثاني .DataSetللجدول الذي يجب أن يستقبل البيانات في الـ

ومثال على ذلك : وتجهيزه ،DataAdapterالكود التالي يبين كيف يتم إنشاء الكائن

لتغيير اسم الجدول الذي يجب أنTableMappingsواستخدام الخاصية وفي النهاية نعرض مربع رسالةDataSetيستقبل البيانات داخل الـ

توضح اسم الجدول مع عدد سجالته ..

كودDim selectCommandText As String = "SELECT * FROM [Information]"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.TableMappings.Add)"Table", "Info"(instance_adapter.Fill)ds(Dim strMsg As String = String.Format)"Count of Records In The {0} Table = {1} .", _    ds.Tables)0(.TableName, ds.Tables)0(.Rows.Count(MsgBox)strMsg, MsgBoxStyle.Information(

مالحظة هامة : )) لو كان األمر مجرد تغير اسم الجدول ، فإنه يغنينا عن كل هذا العناء ، مجرد كتابة االسم المقترح للجدول خالل استدعاء الخاصية

Fill.. وهذه هي اإلعادة للكود الالزم لعمل مثل ذلك ، Å كما ذكرنا سابقا

كود

Page 35: ADO.Net - Arabic

instance_adapter.Fill)ds, "Demo"(

هذا رائي الشخصي (( .

ليس ذلك فقط بل نستطيع كذلك تغيير أسماء الحقول ) األعمدة ( الموجودة دخل الجدول إلى أسماء ذو معنى أوضح ، وذلك من خالل

، وهيTableMappings التابعة للخاصية ColumnMappingsالخاصية � تحتاج إلى تمرير متغيرين من نوع التابعة لها ،Add للخاصية Stringأيضا

وهو اسم العمود األساسي في قاعدة البيانات ،SourceColumnاألول وهو االسم الجديد الذي نريده للعمود فيDataSetColumnوالثاني

.DataSetالجدول المخزن في الـ ولعل التمثيل الذي في الصورة التالية يوضح الفكرة ...

ومثال على ذلك : وتجهيزه ،DataAdapterالكود التالي يبين كيف يتم إنشاء الكائن

لتغيير اسم الجدول الذي يجب أنTableMappingsواستخدام الخاصية ، ويلي ذلك نقوم باستخدام الخاصيةDataSetيستقبل البيانات داخل الـ

ColumnMappingsأننا سوف نشير � لتغيير أسماء بعض الحقول ) علما ( وذلك كي نخبر هذه الخاصية أننا0 بالرمز )Tableللجدول االفتراضي

نريد أن يتم إجراء التعديالت عليه (، وفي النهاية نعرض مربع رسالة توضحاسم الجدول مع عدد سجالته ، واسم العمود الثاني في الجدول ..

كودDim selectCommandText As String = "SELECT * FROM [Information]"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSet

Page 36: ADO.Net - Arabic

instance_adapter.TableMappings.Add)"Table", "Info"(instance_adapter.TableMappings)0(.ColumnMappings.Add)"Name", "First Name"(instance_adapter.TableMappings)0(.ColumnMappings.Add)"ID", "InfoID"(instance_adapter.Fill)ds(Dim strMsg As String = String.Format)"Count of Records In The {0} Table = {1} .{2}The      name Of the second Column Is It : {3} ."(, _    ds.Tables)0(.TableName, ds.Tables)0(.Rows.Count, vbNewLine,         ds.Tables)0(.Columns)0(.ColumnName (MsgBox)strMsg, MsgBoxStyle.Information(

مالحظة هامة : )) لو كان األمر مجرد تغير أسماء األعمدة ، فإنه يغنينا عن في جملة االستعالم ، وهذا هو الكودASكل هذا العناء ، مجرد كتابة عبارة

الالزم لعمل مثل ذلك ..

كودDim selectCommandText As String = "SELECT ID AS [Info ID], Name AS [First Name] FROM [Information]"

هذا رائي الشخصي (( .

� على ذلك لو أننا أردنا تحميل البيانات من وهناك استخدامات أخرى ، مثاال واحد ، وللقيام بذلك علينا أنDataAdapterجدولين مختلفين من خالل

نتأمل المثال التالي حيث يقوم بتوضيح الفكرة : وتجهيزه ، واستخدامDataAdapterفي البداية يتم إنشاء الكائن

Info لتغيير اسم الجدول األول ) وليكن أسمة TableMappingsالخاصية ، ويلي ذلك نقومDataSet( الذي يجب أن يستقبل البيانات داخل الـ

لتغيير أسماء بعض الحقولColumnMappingsباستخدام الخاصية � أننا سوف نشير للجدول االفتراضي ( وذلك كي0 بالرمز )Table) علما

نخبر هذه الخاصية أننا نريد أن يتم إجراء التعديالت عليه (، وبعد ذلكÈر القيمة Fillنستدعي الخاصية DataSetTable لتحميل البيانات ، ثم نغي

إلى اسم الجدول الثاني ، والذي سوف نعطيهTableMappingsالخاصة ( ، ونقوم بتغيير اسم أحدDataSet ) كل ذلك يتم داخل الـ Noteاالسم

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

فإن البيانات الجديدة ستذهب مباشرة إلى الجدول المسمىFillالخاصية Note وبذلك نكون قد حصلنا على جدولين من خالل ، DataAdapter

واحد ، وفي نهاية المطاف كي نتأكد من صحة التغييرات والمدخالت ،نعرض مربع رسالة تخبرنا ببعض التفاصيل المتعلقة بالجدولين ..

كودDim selectCommandText As String = "SELECT * FROM [Information]"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _

Page 37: ADO.Net - Arabic

    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.TableMappings.Add)"Table", "Info"(instance_adapter.TableMappings)0(.ColumnMappings.Add)"Name", "FirstName"(instance_adapter.TableMappings)0(.ColumnMappings.Add)"ID", "InfoID"(instance_adapter.Fill)ds(instance_adapter.TableMappings)0(.DataSetTable = "Note"instance_adapter.TableMappings)0(.ColumnMappings.Add)"Note", "MyNote"(instance_adapter.SelectCommand.CommandText = "SELECT * FROM [Note]"instance_adapter.Fill)ds(Dim strMsg As String = String.Format)"Count of Records In The {0} Table = {1} ." _    & "{2} The name Of the second Column Is It : {3} ." _    & "{4}Count of Records In The {5} Table = {6} ." _    & "{7} The name Of the second Column Is It : {8} .", _    ds.Tables)0(.TableName, ds.Tables)0(.Rows.Count, vbNewLine, _    ds.Tables)0(.Columns)0(.ColumnName, _    vbNewLine, ds.Tables)1(.TableName, ds.Tables)1(.Rows.Count, vbNewLine, _    ds.Tables)1(.Columns)1(.ColumnName(MsgBox)strMsg, MsgBoxStyle.Information(

:FillSchema* الخاصية يحمل بنية البياناتDataAdapterتجعل هذه الخاصية الخاصة بالكائن

بدون تحميل أيةDataSetالموجودة في الجدول المختار إلى الكائن ولكنها ال تنسخFillبيانات ، وبعبارة أخرى هذه الخاصية مشابهة للخاصية

البيانات معها . ولها ثالثة متغيرات ) بارامترات ( :.DataSet- المتغير األول هو الـ

ومن خالله نخبر هذه الخاصية فيما إذاSchemaType- المتغير الثاني هو الخاص بالكائنTableMappingsكان يتوجب عليها استخدام

DataAdapterأم ال ، و لهذا المتغير قيمتين تتحكم في ذلك األولى Mapped ينصح في استخدامه في الغالب ( وهي تجعل ( DataAdapter

. والقيمة الثانيةTableMappingsيستعمل البنية التي حددت له من قبل يتجاهل البنية التي حددت له منDataAdapter وهي تجعل Sourceهي وينشئ بنية تطابق بنية قاعدة البيانات .TableMappingsقبل

يشير إلى االسم المقترح للجدولsrcTable- المتغير الثالث إختياري وهو بغض النظر عن قيمةDatasetالذي نريد نسخ تكوينه في الـ

SchemaType. ومثال على ذلك :

وتجهيزه ،DataAdapterالكود التالي يبين كيف يتم إنشاء الكائن بالجدول المحدد فيDataSet لتعبئة الـ FillSchemaواستخدام الخاصية

جملة االستعالم ( بدون تحميل أي بيانات ( ، وسوف نستخدم المتغيرSchemaType.Mapped لكي نجعل DataAdapterيستعمل البنية

، ومن بعد ذلك نعرض مربعTableMappingsالتي حددت له من قبل رسالة تخبرنا بعدد السجالت المتوفرة في الجدول الذي تم تخزينه في

Page 38: ADO.Net - Arabic

DataSet.. � للتو وذلك للتأكد من أنها تساوي صفرا

كودDim selectCommandText As String = "SELECT * FROM Information"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.TableMappings.Add)"Table", "Demo"(instance_adapter.TableMappings)0(.ColumnMappings.Add)"Name", "FirstName"(instance_adapter.FillSchema)ds, SchemaType.Mapped(Dim strMsg As String = String.Format)"Count of Records In The {0} Table = {1} .", _ds.Tables)0(.TableName, ds.Tables)0(.Rows.Count(MsgBox)strMsg, MsgBoxStyle.Information(

يستعملDataAdapter أن تجعل FillSchemaولو أردنا من الخاصية ، مع إعطاء الجدول اسمTableMappingsالبنية التي حددت له من قبل

بالكود التالي ..11مختلف ، نستبدل السطر رقم

كودinstance_adapter.FillSchema)ds, SchemaType.Mapped , "Info"(

أن تتجاهل البنية التي حددت له منFillSchemaولو أردنا من الخاصية وتنشئ بنية تطابق بنية قاعدة البيانات ، نستبدلTableMappingsقبل

بالكود التالي ..11السطر رقم

كودinstance_adapter.FillSchema)ds, SchemaType.Source(

االسمDataSetفي هذه الحالة سوف يصبح اسم الجدول داخل الـ .Tableاالفتراضي

أن تتجاهل البنية التي حددت له منFillSchemaولو أردنا من الخاصية وتنشئ بنية تطابق بنية قاعدة البيانات ، معTableMappingsقبل

بالكود11إعطاء الجدول اسم ذو معنى أوضح ، نستبدل السطر رقم التالي ..

كود

Page 39: ADO.Net - Arabic

instance_adapter.FillSchema)ds, SchemaType.Source , "Demo"(

** هنا ينتهي حديثنا اليوم ، فما أصبنا من صواب فمن الله وتوفيقه ، وما أصبنا من خطأ فمن أنفسنا والشيطان ، لذلك من وجد أي أخطاء

.. � فليصححها لنا ، أو يخبرنا به كي نصححه ، مشكورا� من الراحة ، لكي نستوعب هذه الجرعة من المعلومات ولنأخذ قسطا

ونصحح أخطائها إن وجدت ، ونعلق على الغير مفهوم منها ، و نكمل فيما� ألن الحديث عن الكائن بعد شرح ما تبقى من الدرس ، ونظرا

DataAdapterطويل و ممتع فلقد قمنا للتو بشرج جزء ، وفي موضوع درسنا القادم إن شاء الله سوف نكمل الجزء اآلخر وهو الحديث عن

وما يلحق بها ..UpDateالخاصية

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

=============

:UpDateالخاصية ينسخ التغييرات بشكل عكسيDataAdapterتجعل هذه الخاصية الكائن

إلى مصدر قاعدة البيانات ، وذلك من خالل تنفيذDataSetمن الكائن ، InsertCommand ، UpDateCommandاألوامر

DeleteCommand وذلك لكل أسطر DataSetألتي قد أدخلت أو عدلت أو حذفت . و سوف نقوم بشرح كل واحد من هذه األوامر على

� أنه يمكننا استخدام باني األوامر حده ونبين كيف يعمل ، علماCommandBuilderليقوم هو ببناء األوامر الالزمة والتي سبق ذكرها

� سوف نقوم بشرحه بالتفصيل . نيابة عنا ، وهو أيضا إلى أكثر من جدول ، لذلك للقيامDatasetكما نعلم ربما يحتوي الـ

بعملية التحديث نحتاج إلى تحديد الجدول الذي نرغب في تحديثه كما فيالمثال ..

كودinstance_adapter.Update)ds, "Information"(

أو الكود التالي ..

كودinstance_adapter.Update)ds.Tables)"Information"((

Page 40: ADO.Net - Arabic

أو الكود التالي في حالة معرفتنا بالرقم ألفهرسي للجدول المخزن في الـDataSet..

كودinstance_adapter.Update)ds.Tables)0((

مالحظة هامة : لتغيير االسم لجدول أو ألعمدةTableMappingsإذا استخدمت الخاصية

� من استخدام نفس التحويالت جدول ما عند تحميل البيانات ، فكن متأكداعند القيام بعملية التحديث .

:InsertCommand- األمر DataAdapte أحد خصائص الكائن InsertCommandيعد أمر اإلضافة

و عمله األساسي هو إضافة سجل جديد إلى سجالت الجدول ، والطريقة� لكائن األمر الذي قد تحدثنا عنه في الوضع التي يعمل بها مشابهة تماما

المتصل ، والمثال التالي موضح بالشرح ، حيث أنه في البداية سوف نقوم بالبيانات ، و نقوم بتحديثDataSetبتجهيز الكائنات للعمل ، ثم نمأل الـ

بشكلDataSetبياناته ، ثم نقوم بنسخ التغييرات التي طرأت على الـ إلى مصدر قاعدة البيانات ، من خال الكائنDataSetعكسي من الكائن

DataAdapter وكائن األمر InsertCommandالتابع له ، وفي األخير لتولي مسؤلية عملية النسخ ، فلنلقي نظرةUpDateنستخدم الخاصية

متفحصة على الكود ..

كود1 Dim selectCommandText As String = "SELECT * FROM Information;"2 Dim selectConnection As OleDbConnection = New OleDbConnection _3     )"Provider=Microsoft.Jet.OLEDB.4.0;" _4     & "Data Source=|DataDirectory|\Note.mdb;" _5     & "User Id=admin;" _6     & "Jet OLEDB:Database Password=ado.net;"(

7 Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(8 Dim ds As New DataSet

9 instance_adapter.Fill)ds, "Information"(

10 Dim MyDR As DataRow = ds.Tables)"Information"(.NewRow11 MyDR.Item)"Name"( = "Yaser Mohamed"12 MyDR.Item)"Age"( = "32"13 MyDR.Item)"Phone"( = "0123456789"14 MyDR.Item)"Email"( = "[email protected]"15 ds.Tables)"Information"(.Rows.Add)MyDR(

16 Dim InsertCommand As New OleDbCommand17 InsertCommand.Connection = selectConnection18 InsertCommand.CommandText = "INSERT INTO Information )[Name],[age],

Page 41: ADO.Net - Arabic

[phone],[email]( VALUES )?,?,?,?("19 InsertCommand.CommandType = CommandType.Text20 InsertCommand = InsertCommand21 InsertCommand.Parameters.AddWithValue)"?", "Yaser Mohamed"(22 InsertCommand.Parameters.AddWithValue)"?", "32"(23 InsertCommand.Parameters.AddWithValue)"?", "0123456789"(24 InsertCommand.Parameters.AddWithValue)"?", "[email protected]"(

25 instance_adapter.InsertCommand = InsertCommand

26 Me.BindingContext)ds, "Information"(.EndCurrentEdit)(27 instance_adapter.Update)ds, "Information"(

28 MsgBox)"Update Successfully...", MsgBoxStyle.Information(

شرح الكود السابق متزامن مع أرقام األسطر : - التصريح عن متغير لإلستعالم عن الجدول المخزن في مصدر البيانات )1

Data Sources. ) - التصريح عن متغير لكائن اإلتصال بقدعدة البيانات .2 ) وهو الوسيط بين الكائنDataAdapter- التصريح عن متغير للكائن 7

DataSet. و مصدر البيانات ( و تجهيزه .DataSet- التصريح عن متغير الكائن 8 - استيراد البيانات من مصدر البيانات ، وتعبئتها في جدول محدد ضمن9

.DataSetالكائن - الكود الالزم إلضافة سجل جديد إلى سجالت الجدول المخزن في10

، حيث يبدأ بالتصريح عن متغير كائن صف ، وتجهيزه منDataSetالكائن ، ثم استدعاء الخاصيةDataSetخالل ربطه بالجدول الموجود في الكائن

صف جديد . - بعد ذلك نقوم بإسناد البيانات المحدثه إلى الحقول الخاصة بالجدول11

( .14 إلى 11ويتكرر ذلك في كل من االسطر رقم ) - نقوم بإضافة كائن الصف إلى صفوف الجدول الموجود في الكائن15

DataSet وبذلك نكون قد حدثنا الجدول المخزن في الكائن ،DataSet. إلى مصدرDataSet- ولكي نقوم بتصدير البيانات الجديده من الكائن 16

البيانات ، نحتاج إلى اعداد وتجهيز كائن األمر الخاص بإضافة صف جديد ، وذلك من خالل إنشاء كائن أمر وإعداده كما كنا نعمل في الوضع

( .24 إلى 16المتصل ، وذلك نجده في كل من االسطر رقم ) - بعد ذلك نقوم بإسناد كائن األمر إلى الخاصية الخاصة بأمر اإلضافة25

.DataAdapterفي الكائن - وللقيام بعملية التحديث النهائية لمصدر البيانات نحتاج إلى إيقاف26

، وذلكDataSetعملية التحديث على الجدول المطلوب ضمن الكائن � على تزامن البيانات . حفاظا

- هنا نقوم بعملية التحديث بعد تحديد اسم الجدول الذي نرغب في27تحديثه .

- مربع رسالة تخبرنا بنجاح العملية .28

Page 42: ADO.Net - Arabic

ويكمن كتابة الكود السابق بشكل أخر وسوف يؤدي نفس النتيجة ،فلنتأمل الكود التالي ..

كود1 Dim selectCommandText As String = "SELECT * FROM Information;"2 Dim selectConnection As OleDbConnection = New OleDbConnection _3     )"Provider=Microsoft.Jet.OLEDB.4.0;" _4     & "Data Source=|DataDirectory|\Note.mdb;" _5     & "User Id=admin;" _6     & "Jet OLEDB:Database Password=ado.net;"(

7 Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(8 Dim ds As New DataSet

9 instance_adapter.Fill)ds, "Information"(

10 Dim MyDR As DataRow = ds.Tables)"Information"(.NewRow11 MyDR.Item)"Name"( = "Yaser Mohamed"12 MyDR.Item)"Age"( = "32"13 MyDR.Item)"Phone"( = "0123456789"14 MyDR.Item)"Email"( = "[email protected]"15 ds.Tables)"Information"(.Rows.Add)MyDR(

16 instance_adapter.InsertCommand = New OleDbCommand)"INSERT INTO Information )[Name],[age],[phone],[email]( VALUES )?,?,?,?(" , selectConnection(

17 instance_adapter.InsertCommand.Parameters.Clear)(18 instance_adapter.InsertCommand.Parameters.AddWithValue)"?", "Yaser Mohamed"(19 instance_adapter.InsertCommand.Parameters.AddWithValue)"?", "32"(20 instance_adapter.InsertCommand.Parameters.AddWithValue)"?", "0123456789"(21 instance_adapter.InsertCommand.Parameters.AddWithValue)"?", "[email protected]"(

22 Me.BindingContext)ds, "Information"(.EndCurrentEdit)(33 instance_adapter.Update)ds, "Information"(

24 MsgBox)"Update Successfully...", MsgBoxStyle.Information(

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

إلى مصدرDataSet- ولكي نقوم بتصدير البيانات الجديده من الكائن 16 التابعInsertCommandالبيانات نحتاج إلى اعداد وتجهيز كائن األمر

والخاص بإضافة صف جديد وذلك من خالل إسنادDataAdapterللكائن الالزمة لعملية اإلضافة ، و كائنSQLكائن أمر جديد وإعداده بجملة

. � االتصال الالزم أيضا - بعد ذلك نحتاج إلى إضافة البارامترات التي تم تعشيشها في جملة17

SQLالسابقة الذكر ، مع قيمها المحدثة ، وذلك نجده في كل من األسطر ( .21 إلى 17رقم )

Page 43: ADO.Net - Arabic

:DeleteCommand- األمر DataAdapte أحد خصائص الكائن DeleteCommandيعد أمر الحذف

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

والتي تشير إلىSQL في جملة Where، حيث سنحتاج إلى وجود فقرة بارامتر ) معامل ( يساعدنا في تحديد السجل المطلوب حذفه ، والمثال التالي موضح بالشرح ، حيث أنه في البداية سوف نقوم بتجهيز الكائنات

بالبيانات ، و نقوم بحذف السجل الحالي منDataSetللعمل ، ثم نمأل الـ ) تعتبر عمليه الحذف هذه تحديثDataSetالجدول المخزن في الكائن

( ، ثمDataSetللسجالت الموجودة في الجدول المخزن في الكائن بشكل عكسي منDataSetنقوم بنسخ التغييرات التي طرأت على الـ

إلى مصدر قاعدة البيانات ، وذلك من خال الكائنDataSetالكائن DataAdapter وكائن األمر DeleteCommandالتابع له ، وفي األخير

لتولي مسؤلية عملية النسخ ، فلنلقي نظرةUpDateنستخدم الخاصية متفحصة على الكود ..

كود1 Dim selectCommandText As String = "SELECT * FROM Information order by name"2 Dim selectConnection As OleDbConnection = New OleDbConnection _3     )"Provider=Microsoft.Jet.OLEDB.4.0;" _4     & "Data Source=|DataDirectory|\Note.mdb;" _5     & "User Id=admin;" _6     & "Jet OLEDB:Database Password=ado.net;"(

7 Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(8 Dim ds As New DataSet9 instance_adapter.Fill)ds, "Information"(

10 Dim MYPosition As String = Me.BindingContext)ds, "Information"(.Position11 Dim IdValue As String = ds.Tables)"Information"(.Rows)MYPosition(.Item)"ID"(

12 Me.BindingContext)ds, "Information"(.RemoveAt)MyPosition(

13 instance_adapter.DeleteCommand = New OleDbCommand)"DELETE FROM Information WHERE  Information.ID=?;", selectConnection(

14 instance_adapter.DeleteCommand.Parameters.Clear)(15 instance_adapter.DeleteCommand.Parameters.AddWithValue)"?",IdValue(

16 Me.BindingContext)ds, "Information"(.EndCurrentEdit)(17 instance_adapter.Update)ds, "Information"(

18 MsgBox)"DELETED Successfully...", MsgBoxStyle.Information(

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

�ر عن موضع السجل الحالي في الجدول10 - نقوم بتخزين الرقم الذي يعب

Page 44: ADO.Net - Arabic

، وذلك من أجل عملية الحذف من داخلDataSetالمخزن داخل الكائن .DataSetالـ " الخاص بالسجل الحاليID- نقوم بتخزين قيمة رقم الحقل المسمى "11

، وذلك من أجل عملية الحذفDataSetللجدول المخزن داخل الكائن من مصدر قاعدة البيانات .

لحذف السجل الحالي ) والذيRemoveAt- نقوم هنا باستخدام األمر 12 ( من الجدول المخزن فيMYPositionقمنا بتخزين قيمته في المتغير

والذي قمنا بتحديد اسمه ، عندئذ يتم حذف السجل منDataSetالكائن فقط .DataSetداخل الـ

إلى مصدرDataSet- ولكي نقوم بتصدير البيانات المحدثة من الكائن 13 التابعDeleteCommandالبيانات نحتاج إلى إعداد وتجهيز كائن األمر

والخاص بحذف سجل ، وذلك من خالل إسناد كائنDataAdapterللكائن الالزمة لعملية الحذف ، و كائن االتصالSQLأمر جديد وإعداده بجملة

. � الالزم أيضا SQL- بعد ذلك نحتاج إلى إضافة البارامتر الذي تم تعشيشه في جملة 14

� في المتغير السابقة الذكر ، مع قيمته والتي قمنا بتخزينها سابقاMyFieldValue ( 15 ، 14 ، وذلك نجده في كل من السطرين رقم. )

:UpdateCommand- األمر أحد خصائص الكائنUpdateCommandيعد أمر التحديث

DataAdapteو عمله األساسي هو تحديث سجل محدد من سجالت � لكائن األمر الذي قد الجدول ، والطريقة التي يعمل بها مشابهة تماما

Whereتحدثنا عنه في الوضع المتصل ، حيث سنحتاج إلى وجود فقرة والتي تشير إلى بارامتر ) معامل ( يساعدنا في تحديدSQLفي جملة

السجل المطلوب تحديثه ، والمثال التالي موضح بالشرح ، حيث أنه في بالبياناتDataSetالبداية سوف نقوم بتجهيز الكائنات للعمل ، ثم نمأل الـ

، و نقوم بعد ذلك بتحديث بيانات السجل الحالي للجدول المخزن في ، ثم نقوم بنسخ التغييرات التي طرأت على الـDataSetالكائن

DataSet بشكل عكسي من الكائن DataSetإلى مصدر قاعدة وكائن األمرDataAdapterالبيانات ، وذلك من خال الكائن

UpdateCommand التابع له ، وفي األخير نستخدم الخاصية UpDate لتولي مسؤلية عملية النسخ ، فلنلقي نظرة متفحصة على الكود ..

كود1 Dim selectCommandText As String = "SELECT * FROM Information"2 Dim selectConnection As OleDbConnection = New OleDbConnection _3     )"Provider=Microsoft.Jet.OLEDB.4.0;" _4     & "Data Source=|DataDirectory|\Note.mdb;" _5     & "User Id=admin;" _6     & "Jet OLEDB:Database Password=ado.net;"(

7 Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(8 Dim ds As New DataSet

Page 45: ADO.Net - Arabic

9 instance_adapter.Fill)ds, "Information"(

10 Dim MyPosition As Integer = Me.BindingContext)ds, "Information"(.Position11 Dim IdValue As String = ds.Tables)0(.Rows)MyPosition(.Item)"ID"(

12 ds.Tables)0(.Rows)MyPosition(.Item)"Name"( = "Yaser AL-Shikh"13 ds.Tables)0(.Rows)MyPosition(.Item)"Age"( = "32"14 ds.Tables)0(.Rows)MyPosition(.Item)"Phone"( = "123456789"15 ds.Tables)0(.Rows)MyPosition(.Item)"Email"( = "[email protected]"

16  instance_adapter.UpdateCommand = New OleDbCommand)"UPDATE Information set Name=?, Age=?, Phone=?, Email=? WHERE Id =?", selectConnection(

17 instance_adapter.UpdateCommand.Parameters.Clear)(18 instance_adapter.UpdateCommand.Parameters.AddWithValue)"?", "Yaser AL-Shikh"(19 instance_adapter.UpdateCommand.Parameters.AddWithValue)"?", "25"(20 instance_adapter.UpdateCommand.Parameters.AddWithValue)"?", "123456789"(21 instance_adapter.UpdateCommand.Parameters.AddWithValue)"?", "[email protected]"(22 instance_adapter.UpdateCommand.Parameters.AddWithValue)"?", IdValue(

23 Me.BindingContext)ds, "Information"(.EndCurrentEdit)(24 instance_adapter.Update)ds.Tables)"Information"((

25 MsgBox)"Update Successfully...", MsgBoxStyle.Information(

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

, Name , Age ,Phone- نقوم هنا بتحديث حقول السجل الحالي ) 12Email في الجدول المخزن داخل الكائن ) DataSetوذلك نجده في ،

(15 ، 12كل من السطور رقم ) إلى مصدرDataSet- ولكي نقوم بتصدير البيانات المحدثة من الكائن 16

التابعUpdateCommandالبيانات نحتاج إلى إعداد وتجهيز كائن األمر والخاص بتحديث سجل ، وذلك من خالل إسنادDataAdapterللكائن

الالزمة لعملية التحديث ، و كائنSQLكائن أمر جديد وإعداده بجملة . � االتصال الالزم أيضا

- بعد ذلك نحتاج إلى إضافة البارامترات التي تم تعشيشها في جملة17SQLالسابقة الذكر ، مع قيمها الخاصة بها ، وكذلك البارامتر الخاص

� في المتغير بتحديد السجل المراد تحديثه والذي قمنا بتخزين قيمته سابقاIdValue ( 22 إلى 17 ، وكل ذلك نجده في السطور رقم. )

Updateوقبل أن نختم الحديث عن عملية التحديث باستخدام الخاصية أريد أن أبين أنه عند قيام هذا األمر بالعمل فإنه يقوم باختبار حالة الصف ، ويقوم بتنفيذ األمر المطلوب سواء كان إضافة أو تحديث أو حذف ، وذلك

Page 46: ADO.Net - Arabic

بشكل متكرر لكل صف من الصفوف ، حيث أن تحديث الصفوف ال يتمدفعة واحده ، إنما يتم تحديث كل صف بشكل منفرد .

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

abetry.. وهي كما يلي على التوالي ،

ÉمDataSet للكائن DataRow. القيم التي أدخلت في 1 ÉنتقلÅ إلى قÚي ت الخاصة بالتحديث ) اإلضافة أوSQLالبارامترات التي تم وضعها في جÅمل

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

في اإلقالع .OnRowUpdating. يبدأ الحدث 2 ) سواء كان هذاSQL. يتم تنفيذ أمر التحديث الذي تم كتابته في جملة 3

التحديث لإلضافة أو التعديل أو الحذف ( .جاع السجلÚ األول ، فإن النتيجة األولى التي تعود يكون4 Ûإذا األمر أعد إلر .

. *DataRowموقعها في الـ . *DataRow. إذا كان هناك بارامترات ناتجه، فإنهم يوضÅوعون في الـ 5 في اإلقالع .OnRowUpdated. يبدأ الحدث 6 .DataSet من الكائن AcceptChanges. يتم استدعاء الخاصية 7

( لست على دراية تامة بها ولكني نقلتها بعد أن قمت5 ، 4* رقمي ) لعله يوجد من يستفيد منها أو يوضحها لنا ، ونصهاMSDNبترجمتها من

األساسي هو :]ltr[4 -If the command is set to FirstReturnedRecord, the first

returned result is placed in the DataRow.5 -If there are output parameters, they are placed in the

DataRow./]ltr[

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

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

أجل الشرح والفهم لما يدور خلف الكواليس فقط ، وسوف نعيد كتابة.. � االكواد السابقة بشكل مختصر ، وذلك عندما نتقدم في الدرس قليال

Page 47: ADO.Net - Arabic

� من الراحة ، لكي نستوعب هذه ** هنا ينتهي حديثنا اليوم ، ونأخذ قسطا الجرعة من المعلومات ونصحح أخطائها إن وجدت ، ونعلق على الغير

مفهوم منها ، و نكمل فيما بعد شرح ما تبقى من الدرس وذلك فيالمشاركات القادمة ..

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

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

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوب إليك

=============

:CommandBuilderالكائن يستخدم كائنات األوامر )DataAdapterمن المعلوم أن الكائن

SelectCommand ، InsertCommand ، UpdateCommand ، DeleteCommandالختيار أو إضافة أو تحديث أو حذف السجالت في )

قاعدة البيانات ، وحيث أنه يجب على هذه الكائنات استخدام الكائنOleDbParamter أو ( SqlParamterلتحديد القيم التي يجب )

استخدامها لمعالجة قاعدة البيانات ، فإنه ولحسن الحظ ال يتوجب علينا إنشاء تلك الكائنات ) اإلضافة أو التحديث أو الحذف وكذلك البارامترات (

) والذيCommandBuilderبأنفسنا ، وذلك عندما نستخدم الكائن ، حيثDataAdapterيسمى باني األوامر ( و القيام بربطه بالكائن

سوف يتولى هو بإعداد األوامر الالزمة و البارامترات المناسبة .� ، وهي كما في الكود التالي .. وطرقة تجهيزه للعمل بسيطة جدا

كودDim MyComB As New OleDbCommandBuilderMyComB.DataAdapter = instance_adapter

ويمكن اختصارها بالشكل التالي ..

كودDim MyComB As New OleDbCommandBuilder)instance_adapter(

لصنعCommandBuilder- ويبين الكود التالي كيف يمكن استخدام إلضافة سجل جديد ..DataAdapterكائن أمر

Page 48: ADO.Net - Arabic

وسوف نستخدم نفس الكود السابق شرحه مع بعض التعديالت الجديدة ، ، وفيDataAdapter بالكائن CommandBuilderوهي ربط الكائن

التي قامSQL نعرض فيها جملة MsgBoxالسطر األخير نعرض CommandBuilder.. ببنائها وكذلك عدد البارامترات التي استخدمها

كودDim selectCommandText As String = "SELECT * FROM Information;"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.Fill)ds, "Information"(

Dim MyDR As DataRow = ds.Tables)"Information"(.NewRowMyDR.Item)"Name"( = "Osamh Mohamed"MyDR.Item)"Age"( = "18"MyDR.Item)"Phone"( = "0123456789"MyDR.Item)"Email"( = "[email protected]"ds.Tables)"Information"(.Rows.Add)MyDR(

Dim MyComB As New OleDbCommandBuilder)instance_adapter(

Me.BindingContext)ds, "Information"(.EndCurrentEdit)(instance_adapter.Update)ds, "Information"(

MsgBox)"Update Successfully...", MsgBoxStyle.Information(MessageBox.Show)String.Format)"The SQL InsertCommand Is :{0}{1}{2}{3}{4}The Count Of Paramters Is: {5}", vbNewLine, vbNewLine, MyComB.GetInsertCommand)(.CommandText, vbNewLine, vbNewLine, MyComB.GetInsertCommand)(.Parameters.Count((

CommandBuilderبعد تنفيذ الكود السابق سوف نشاهد أن الكائن الخاصة بإضافة سجل جديد بشكل احترافي ، وأن عددSQLكون لنا جملة

..4البارامترات التي استخدمها

SQLINSERT INTO Information )Name, Age, Phone, Email( VALUES )?, ?, ?, ?(

لصنعCommandBuilder- ويبين الكود التالي كيف يمكن استخدام لحذف سجل ..DataAdapterكائن أمر

وسوف نستخدم نفس الكود السابق شرحه مع بعض التعديالت الجديدة ، ، وفيDataAdapter بالكائن CommandBuilderوهي ربط الكائن

Page 49: ADO.Net - Arabic

التي قامSQL نعرض فيها جملة MsgBoxالسطر األخير نعرض CommandBuilder.. ببنائها وكذلك عدد البارامترات التي استخدمها

كودDim selectCommandText As String = "SELECT * FROM Information order by name"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSetinstance_adapter.Fill)ds, "Information"(

Dim MYPosition As String = Me.BindingContext)ds, "Information"(.Position

Me.BindingContext)ds, "Information"(.RemoveAt)MYPosition(

Dim MyComB As New OleDbCommandBuilder)instance_adapter(

Me.BindingContext)ds, "Information"(.EndCurrentEdit)(instance_adapter.Update)ds, "Information"(

MsgBox)"DELETED Successfully...", MsgBoxStyle.Information(MessageBox.Show)String.Format)"The SQL DeleteCommand Is :{0}{1}{2}{3}{4}The Count Of Paramters Is: {5}", vbNewLine, vbNewLine, MyComB.GetDeleteCommand)(.CommandText, vbNewLine, vbNewLine, MyComB.GetDeleteCommand)(.Parameters.Count((

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

..9البارامترات التي استخدمها

SQLDELETE FROM Information WHERE ))ID = ?( AND ))? = 1 AND Name IS NULL( OR )Name = ?(( AND ))? = 1 AND Age IS NULL( OR )Age = ?(( AND ))? = 1 AND Phone IS NULL( OR )Phone = ?(( AND ))? = 1 AND Email IS NULL( OR )Email = ?(((

لصنعCommandBuilder- ويبين الكود التالي كيف يمكن استخدام لتحديث بيانات سجل ..DataAdapterكائن أمر

وسوف نستخدم نفس الكود السابق شرحه مع بعض التعديالت الجديدة ، ، وفيDataAdapter بالكائن CommandBuilderوهي ربط الكائن

التي قامSQL نعرض فيها جملة MsgBoxالسطر األخير نعرض CommandBuilder.. ببنائها وكذلك عدد البارامترات التي استخدمها

Page 50: ADO.Net - Arabic

كودDim selectCommandText As String = "SELECT * FROM Information order by name"Dim selectConnection As OleDbConnection = New OleDbConnection _    )"Provider=Microsoft.Jet.OLEDB.4.0;" _    & "Data Source=|DataDirectory|\Note.mdb;" _    & "User Id=admin;" _    & "Jet OLEDB:Database Password=ado.net;"(Dim instance_adapter As New OleDbDataAdapter)selectCommandText, selectConnection(Dim ds As New DataSet

instance_adapter.Fill)ds, "Information"(

ds.Tables)0(.Rows)3(.Item)"Name"( = "Yaser AL-Shikh"ds.Tables)0(.Rows)3(.Item)"Age"( = "32"ds.Tables)0(.Rows)3(.Item)"Phone"( = "0123456789"ds.Tables)0(.Rows)3(.Item)"Email"( = "[email protected]"

Dim MyComB As New OleDbCommandBuilder)instance_adapter(

Me.BindingContext)ds, "Information"(.EndCurrentEdit)(instance_adapter.Update)ds, "Information"(

MsgBox)"Update Successfully...", MsgBoxStyle.Information(MessageBox.Show)String.Format)"The SQL UpdateCommand Is :{0}{1}{2}{3}{4}The Count Of Paramters Is: {5}", vbNewLine, vbNewLine, MyComB.GetUpdateCommand)(.CommandText, vbNewLine, vbNewLine, MyComB.GetUpdateCommand)(.Parameters.Count((

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

..13عدد البارامترات التي استخدمها

SQLUPDATE Information SET Name = ?, Age = ?, Phone = ?, Email = ? WHERE ))ID = ?( AND ))? = 1 AND Name IS NULL( OR )Name = ?(( AND ))? = 1 AND Age IS NULL( OR )Age = ?(( AND ))? = 1 AND Phone IS NULL( OR )Phone = ?(( AND ))? = 1 AND Email IS NULL( OR )Email = ?(((

أريد أن أوضح شيءCommandBuilderوقبل أن نختم الحديث عن � ، وهو أنه قد يحدث عند تعبئتك للكائن بالجدول منDataSetمهم جدا

، تكون هذه الجملة قد احتوت على) SQL ) Selectخالل استخدام جملة استخدام األقواس ) ] [ ( أو على فراغات في تسمية الجدول أو الحقول ،

في تسمية الحقولSQLأو أن ألجملة تحتوي على كلمات محجوزة للغة ، في هذه الحالة يجب علينا إضافة القوسين ) [ ] (DATE و MEMOمثل

، SQL ) InsertCommand ، UpdateCommandلجمل

Page 51: ADO.Net - Arabic

DeleteCommand (التي ينشئها باني األوامر ، ويتم ذلك من خالل � ،QuoteSuffix و QuotePrefixالخاصيتان ، وطرقة عملها سهل جدا

والكود التالي يوضح الطريقة الصحيحة للتحديث من خالل باني األوامر فيمثل هذه الحاالت ..

كودDim MyComB As New OleDbCommandBuilder)instance_adapter(

MyComB.QuotePrefix = "["MyComB.QuoteSuffix = "]"

instance_adapter.InsertCommand = MyComB.GetInsertCommandinstance_adapter.UpdateCommand = MyComB.GetUpdateCommandinstance_adapter.DeleteCommand = MyComB.GetDeleteCommand

Me.BindingContext)ds, "Information"(.EndCurrentEdit)(instance_adapter.Update)ds, "Information"(

� من الراحة ، لكي نستوعب هذه ** هنا ينتهي حديثنا اليوم ، ونأخذ قسطا الجرعة من المعلومات ونصحح أخطائها إن وجدت ، ونعلق على الغير

مفهوم منها ، و نكمل فيما بعد شرح ما تبقى من الدرس وذلك فيالمشاركات القادمة ..

Bindingمالحظة : موضوعنا القادم سوف يكون " ربط عناصر التحكم Controlsوسوف نتعلم كيف يمكننا إنعاش هذه العناصر وجعلها تنبض ، "

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

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

:-Binding Controlsربط عناصر التحكم

مقدمة : تقوم فكرة ربط عناصر التحكم على ربط البيانات المتوفرة فيDataTable أو DataSetبأحد عناصر التحكم الموجودة في واجهة

المستخدم الرسومية على سبيل المثال :CheckBox ، ComboBox ، DateTimePicker ، Label ، LinkLabel

، ListBox ، ListView ، MonthCalendar ، PictureBox ، ProgressBar ،

RadioButton، RichTextBox ، StatusBar ، TextBox ، TreeView ،

Page 52: ADO.Net - Arabic

DataGridView... هذا فقط على سبيل المثال ال الحصر ، وبعد أن يتم ربط عناصر التحكم

بمصدر البيانات ، فإنه يتم إنعاشها فتصبح تنبض بالحياة ، حيث أن أي� عليها وكذلك العكس تغييرات تتم على مصدر البيانات ستنعكس تلقائيا حيث أن أي تغيير يتم على قيم هذه العناصر فإنه ينعكس على مصدر

التابعةHasChangesالبيانات وفي هذه الحالة لو استدعينا الخاصية . إضافة إلى أن الربطTrue فإنها سوف تعيد القيمة DataSetللكائن

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

تعرض القيم الحالية للبيانات المتوفرة في مصادر البيانات .

طرق ربط البيانات بعناصر التحكم :- Binding atهناك طريقتان لربط البيانات بعناصر التحكم ، أوالهما

design timeأي الربط في وقت التصميم ويتم باستخدام األدوات أي الربط في وقتBinding at run timeوالمعالجات ، واألخرى

التشغيل ويتم باستخدام الكود وهو ما سنقوم بدراسته هنا .

أنواع ربط البيانات بعناصر التحكم :- هناك نوعان من الربط ويعتمدان على نوع عنصر التحكم الذي نريد أن

نربطه بمصدر البيانات ..

( :-Simple-bind control* النوع األول ويسمى الربط البسيط )

( أي قيمة حقلsingle valueوهو يختص بعناصر التحكم التي تستقبل ) ، TextBox ، Lableواحد من مصدر البيانات على سبيل المثال

DateTimePicker ، PictureBox ، MonthCalendar ، ونقوم بتجهيزهBindingوللقيام بعملية الربط سوف نستخدم الكائن

للعمل وذلك عن طريق تزويده ببعض المتغيرات ) البارامترات ( وهيكالتالي :

1 -PropertyName: (The name of the control property to bind)

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

نقوم بتصدير القيمة المخزنة فيها إلى قاعدة البيانات وذلك عند عملية التحديث . وهي تختلف من أداة تحكم إلى أداة أخرى ، فهي يمكن أن تأخذ

، Text ، Tag ، Value ، Checked ، Imageإحدى القيم التالية ))SelectedValue. ))

2 -DataSource: (An Object that represents the data source)

وهو يشير إلى مصدر البيانات ، ونقصد بمصدر البيانات هنا الكائن الذي

Page 53: ADO.Net - Arabic

يحتوي على جدول أو جداول قاعدة البيانات ، ونستطيع أن نحدد على ، DataSetسبيل المثال أي كائن من الكائنات التالية كمصدر بيانات ))

DataTable ، DataView ، DataViewManager ، BindingSource))

3 -DataMember: (The property or list to bind to)

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

4 -formattingEnabled: (true to format the displayed data; otherwise, false)

يسمح بقراءة القيمةTrueوهو متغير اختياري ، له قيمتان إما صائب وهوFalseالمخزنة وتهيئها وتحويلها من صيغة إلى صيغة أخرى أو خاطئ

PictureBoxعكس السابق ، وهو مهم جدا لبعض األدوات أعلم منها من أجل تحويل القيمة المخزنة في قاعدةTrueحيث يجب أن نجعله

كي تتمكن هذه األداة من عرض الصورBitmap إلى byteالبيانات من ) اجتهاد فردي مني ، والله أعلم ( .

DataBindings نقوم بإضافته للخاصية Bindingوبعد تجهيز الكائن التابعة ألداة التحكم . وبذلك نكون قد انتهينا من عملية الربط وأصبحت أداة التحكم متصلة بمصدر البيانات بشكل مباشر . ولعل المثال التالي

يساعد في توضيح ما سبق : كمصدر بيانات وفيه جدول يحمل اسمDataSetلنفرض أن لدينا كائن

Information ويوجد بهذا الجدول عمود يحمل اسم Nameونريد أن ، بقيم حقول العمودTextBox التابعة ألداة التحكم Textنربط الخاصية

Name.. كي يتم ذلك فلنلقي نظرة على الكود التالي ،

كودDim bindName As BindingbindName = New Binding)"Text", MyDataSet.Tables)"information"(, "Name"(TextBox.DataBindings.Add)bindName(

يمكننا كتابة الكود السابق بالشكل التالي ..

كودDim bindName As BindingbindName = New Binding)"Text", MyDataSet, "information.Name"(TextBox.DataBindings.Add)bindName(

ويكن اختصار الكود السابق بالشكل التالي ..

كود

Page 54: ADO.Net - Arabic

Dim bindName As New Binding)"Text", MyDataSet, "information.Name"(TextBox.DataBindings.Add)bindName(

ويكن اختصار الكود السابق بالشكل التالي ..

كودTextBox.DataBindings.Add)New Binding)"Text", MyDataSet, "information.Name"((

بعد ذلك سوف نجد أن أداة التحكم تعرض لنا قيمه أول حقل من حقول واإلبحارName ، وعند القيام بالتنقل بين حقول العمود Nameالعمود

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

وهذه بعض الصور لعمليات الربط البسيط لبعض أدوات التحكم :

كودTextBox.DataBindings.Add)New Binding)"Text", MyDataSet, "information.Name"((TextBox.DataBindings.Add)New Binding)"Tag", MyDataSet, "information.Name"((Lable.DataBindings.Add)New Binding)"Text", MyDataSet, "information.ID_Student"((CheckBox.DataBindings.Add)New Binding)"Checked", MyDataSet, "information.Good"((CheckBox.DataBindings.Add)New Binding)"Tag", MyDataSet.Tables)"information"(, "Good"(DateTimePicker1.DataBindings.Add)New Binding)"Text", MyDataSet, "information.date"((DateTimePicker1.DataBindings.Add)New Binding)"Value", MyDataSet, "information.date"((PictureBox.DataBindings.Add)New Binding)"Image", MyDataSet, "imageData", True((

( :Complex-bind control* النوع الثاني ويسمى الربط المركب ) ( أي عدةmultiple valuesوهو يختص بعناصر التحكم التي تستقبل )

ComboBox ، ListBox ( من مصدر البيانات مثل DataColumnقيم ) . وللقيامDataGridView ( مثال DataTableأو مصدر بيانات كامل )

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

أننا في الربط المركب نستطيع أن نربط أدوات التحكم إما لعرض البياناتفقط أو للعرض والتحديث ، وسنتناول الطريقتين في السطور القادمة .

يجب في البداية تجهيز بعض خصائص أداة التحكم ، وهي تختلف من أداةتحكم إلى أداة تحكم أخرى ، وهي كما يلي :

:DataSource- الخاصية 1 ونقوم بتمرير مصدر البيانات لهذه الخاصية ، ونقصد بمصدر البيانات هنا

الكائن الذي يحتوي على جدول قاعدة البيانات والذي نريد أن نعرض بياناته على هذه األداة ، ونستطيع أن نحدد على سبيل المثال أي كائن من

Page 55: ADO.Net - Arabic

DataSet ، DataTableالكائنات التالية كمصدر بيانات لهذه الخاصية )) ، DataView ، DataViewManager ، BindingSource))

2 -DisplayMember: ونقوم بتمرير قيمة نصية لهذه الخاصية تحمل اسم العمود الموجود في

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

3 -ValueMember: ) اختياري ( وتظهر أهمية هذه الخاصية في حالة كنا نريد أن نعرض للمستخدم قيمة

" التيDisplayMemberأحد األعمدة ) وذلك باستخدام الخاصية " تحدثنا عنها منذ قليل ( ونخزن في قاعدة البيانات قيمة عمود أخر ، حيث

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

4 -DataBindings:) اختياري ( وتظهر أهمية هذه الخاصية في حالة كنا نريد أن نحفظ في قاعدة البيانات

القيمة التي تعرضها أداة التحكم أو القيمة المخزنة في الخاصيةValueMemberوالتي تحدثنا عنها منذ قليل ، ولتجهيز هذه الخاصية

سوف نتبع نفس األسلوب الذي اتبعناه في الربط البسيط والذي تحدثناعنه بالتفصيل فيما سبق .

Complex-bindأمثلة تطبيقية على الربط المركب ألدوات التحكم ) control: )

بقيم العمودListBox- بفرض أننا نريد أن نربط أداة تحكم من نوع 1 " وهو أسماء الطالب ، علما أن هذا العمودNameالذي يحمل اسم " وهذا الجدول مخزن في الكائنStudentsأحد أعمدة الجدول

DataSet.. وللقيام بعملية الربط فلنتفحص الكود التالي ،

كودListBox1.DataSource = MyDataSetListBox1.DisplayMember = "Students.name"

ويمكن كتابة الكود السابق بشكل آخر ..

كودListBox1.DataSource = MyDataSet.Tables)"Students"(ListBox1.DisplayMember = "name"

بالقيم )ComboBox- بفرض أننا نريد أن نمأل أداة التحكم من نوع 2

Page 56: ADO.Net - Arabic

Male , Femaleوذلك بالطريقة التقليدية ، ولكنا أيضا نريد أن نجهز ) األداة نفسها كي تكون قادرة على حفظ القيمة التي يختارها المستخدم

CustomerSexمن القائمة المنسدلة لها في العمود الذي يحمل اسم " وهذا الجدولCustomers" علما أن هذا العمود أحد أعمدة الجدول

، وللقيام بعملية الربط و التجهيز للحفظDataSetمخزن في الكائن فلنتفحص الكود التالي ..

كودComboBox1.Items.Add)"Male"(ComboBox1.Items.Add)"Female"(ComboBox1.DataBindings.Add)New Binding)"Text", MyDataSet.Tables)"Customers"(, "CustomerSex"((

بقيم العمودComboBox- بفرض أننا نريد أن نربط أداة تحكم من نوع 3 " وهو أسماء المدن ، علما أن هذا العمود أحدCityالذي يحمل اسم "

،DataSet وهذا الجدول مخزن في الكائن Informationأعمدة الجدول ونريد أيضا أن نجهز نفس األداة كي تكون قادرة على حفظ القيمة التي

يختارها المستخدم من القائمة المنسدلة لها في العمود الذي يحمل اسم "CustomerCityعلما أن هذا العمود أحد أعمدة الجدول "

CustomerAddresses وهذا الجدول مخزن في الكائن DataSet � ، وللقيام بعملية الربط و التجهيز للحفظ فلنتفحص الكود التالي .. أيضا

كودComboBox1.DataSource = MyDataSet.Tables)"Information"(ComboBox1.DisplayMember = "City"ComboBox1.DataBindings.Add)New Binding)"text", MyDataSet.Tables)"CustomerAddresses"(, " CustomerCity"((

بقيم العمودComboBox- بفرض أننا نريد أن نربط أداة تحكم من نوع 4 " وهو أسماء المدن وذلك من أجل عرض أسماءCityالذي يحمل اسم "

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

الحفظ فيما بعد ، علما أن هذين العمودين من أعمدة الجدولInformation وهذا الجدول مخزن في الكائن DataSetونريد أيضا أن ،

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

" علما أنCustomerCityالمنسدلة لها ، في العمود الذي يحمل اسم " وهذا الجدولCustomerAddressesهذا العمود أحد أعمدة الجدول

� ، وللقيام بعملية الربط و التجهيز للحفظDataSetمخزن في الكائن أيضافلنتفحص الكود التالي ..

Page 57: ADO.Net - Arabic

كودComboBox1.DataSource = MyDataSet.Tables)"Information"(ComboBox1.DisplayMember = "City"ComboBox1.ValueMember = "ID_City"ComboBox1.DataBindings.Add)New Binding)"selectedValue", MyDataSet.Tables)"CustomerAddresses"(, " CustomerCity"((

- بفرض أننا نريد أن نربط مصدر بيانات كامل مثل الجدول5CustomerAddresses هذا الجدول مخزن في الكائن ( DataSetفي )

وذلك من أجل عرض البيانات وحتى التعديلDataGridViewأداة التحكم عليها وحفظها فيما بعد ، فإن األمر بغاية السهولة ، وللقيام بعملية الربط

و التجهيز للحفظ فلنتفحص الكود التالي ..

كودDataGridView1.DataSource = MyDataSetDataGridView1.DataMember = "CustomerAddresses"

ويمكن اختصار الكود كي يصبح بالشكل التالي ..

كودDataGridView1.DataSource = MyDataSet.Tables)"CustomerAddresses"(

� من الراحة ، لكي نستوعب هذه ** هنا ينتهي حديثنا اليوم ، ونأخذ قسطا الجرعة من المعلومات ونصحح أخطائها إن وجدت ، ونعلق على الغير

مفهوم منها ، و نكمل فيما بعد شرح ما تبقى من الدرس وذلك فيالمشاركات القادمة ..

" ،BindingSourceمالحظة : موضوعنا القادم سوف يكون " الكائن من إضافهDatasetوسوف نتعلم كيف يمكننا إدارة العمل على الكائن

وحذف وغيره ، وكذلك اإلبحار في قاعدة البيانات وعمل فلتر الترشيح للبيانات .. إلى أن نلتقي مرة أخرى أترككم في حفظ الله ورعايته .. ياسر

الشيخ

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوبإليك ((

-----------------------------------------------

Page 58: ADO.Net - Arabic

( ## Concurrency violation## إنتهاك التزامن )

نصادف أحيانا أثنا قيامنا بعملية التحديث برسائل مزعجة تسمى بإنتهاك

( ، ويكون نص الرسالة كما يلي :Concurrency violationالتزامن )

"Concurrency violation: the UpdateCommand affected 0 of the

expected 1 records"

أو

"Concurrency violation: the DeleteCommand affected 0 of the

expected 1 records"

.. Zوسوف نناقش هنا السبب والحل معا

DataSetالذي يحصل عندما تضيف سجل جديد في الجدول المخزن في

وعندAutoNumber من نوع Primary Keyوكان العمود المخصص للـ

AutoNumberالقيام بعملية التحديث يجب أن تحصل على قيمة رقم الـ

وإال فإنه سوفAccessالجديد من الجدول المخزن في قاعدة البيانات

لكل من الجدول المخزن فيPrimary Keyيكون هناك إختالف بين رقم

Access والجدول المخزن في DataSetوحينها لو قمنا بعملية التحديث

للسجل فإننا سوف نواجه فشل لعملية التحيث ألننا باختصار تسببنا في

( وهو يحدثConcurrency violationحصول ما يسمى إنتهاك التزامن )

لعمليات التحديث عند اإلضافة والسبب كما أوضحنا أن قيمة رقم الـ

AutoNumber الجديد من الجدول المخزن في قاعدة البيانات Accessغير

الذي سوف يقوم بالتجهيز لعملية التحديث .DataAdapterمتوفره للكائن

الجديدAutoNumberيبقى السؤال هنا : كيف نحصل على قيمة رقم الـ

؟Accessمن الجدول المخزن في قاعدة البيانات

الجواب يتمثل في خطوتين :

مع األحداث التابعة له ، ويتم ذلكDataAdapterاألولى - التصريح للكائن

أثناء التصريح عن المتغير كما يلي :WithEventsبكتابة العبارة

كود

Dim WithEvents MyDataAdapter As New OleDb.OleDbDataAdapter

Page 59: ADO.Net - Arabic

كي ينطلق عندDataAdapter للكائن RowUpdatedالثانية - تجهيز الحدث

الجديد منAutoNumberالقيام بعملية التحديث ويقوم بجلب قيمة رقم الـ

ويستخدمها في اتمام عمليةAccessالجدول المخزن في قاعدة البيانات

التحديث ، وكل ذلك موجود في هذا المثال :

كود

    ' Event Handler for RowUpdated Event

    Private Sub MyDataAdapter_RowUpdated)ByVal sender As Object, ByVal e As

OleDb.OleDbRowUpdatedEventArgs( Handles MyDataAdapter.RowUpdated

        If e.Status = UpdateStatus.Continue AndAlso e.StatementType =

StatementType.Insert Then

            'Get NewID

            Dim cmdGetIdentity As New OleDb.OleDbCommand)"SELECT

@@IDENTITY", cn(

            cmdGetIdentity.CommandType = CommandType.Text

            ' Get the Identity column value

            e.Row)"ID"( = Int32.Parse)cmdGetIdentity.ExecuteScalar)(.ToString)((

            e.Row.AcceptChanges)(

        End If

    End Sub

وبذلك نكون قد تخلصنا من مشكلة انتهاك التزامن حيث لن تظهر عند عملية التحديث ، والله الموفق ، فإن أصبت فبتوفيق الله وحده ، وإن أخطأت فمن

نفسي والشيطان . أخوكم الفقير إلى الله ياسر الشيخ ..

مالحظة : عند التطبيق يجب استبدال بعض العبارات بما يتناب مع برامجكم من االسم الذي اخترتموه لكائن االتصال واسم العمود المخصص للـ

Primary Keyوغيره . وللمزيد من المعلومات أحيلكم على الرابطين التاليين :

http://www.msdner.com/dev-archive/150/2-7-1501099.shtmhttp://support.microsoft.com/default.aspx?...kb;en-us;815629

))سبحانك اللهم وبحمدك، أشهد أن ال إله إال أنت، أستغفرك وأتوب إليك ((

Page 60: ADO.Net - Arabic