BasharVS

قواعد البيانات من 0 إلى الإحترف

34 ردود في هذا الموضوع

هذا المقال سيناقش التعامل مع قواعد البيانات في الـ( Visual Basic.Net ) باستخدام الـ( SQL Server 2005 ) و الـ( Access ) وكل مايتعلق بهذين المحركين .

في بادىء الأمر عليّنا التعرف على الإستعلام وطبيعة عمله وكيفية استغلاله بالشكل المناسب :

الإستعلام هو عبارة عن عملية تقوم بقراءة بيانات محددة من جدول معين بشروط أوبدون شروط، يتولد عن طريق هذا الإستعلام جدول يحمل البيانات التي تحقق شروط الإستعلام إن وجدت .

الإستعلام :

عملية الإستعلام تتم باستخدام الكلمات المحجوزة التالية :

Select

From

Select ( اختيار ) والتي يتبعها إما رمز النجمة أي ( * ) والذي يمثل جميع أسماء الحقول بشكل وهمي، أو يتتبعها أسماء الحقول المراد الإستعلام عنها .

From ( من ) يجب أن يتتبع هذه الكلمة إسم الجدول المراد إستيراد البيانات منه .

أمثلة عن ماسبق :

لنعتبر أنه لدينا جدول ( People ) يحوي معلومات عامة عن أشخاص، ولهذا الجدول أربعة حقول ( المُعرف [iD]، الإسم [FirstName]، الكنية [LastName]، العنوان [Address] ) .

بالنسبة لحقل المٌعرف [iD]، إذا كنت مبتدء بقواعد البيانات ستفهم لاحقاً أن كل جدول يجب أن يحوي مفتاح أساسي يساعد الإستعلام على التمييز بين كل سجل أو صف وذلك لأن هذا المفتاح الأساسي يمثل بحقل اي ( Column ) لايتكرر بخلاياه أي قيمة .

الأن، لنأتي بجميع الحقول المذكورة، كما ذكرنا يمكننا استخدام رمز النجمة لتمثيل أسماء الحقول التابعة للجدول المستخدم في الإستعلام :

Select * From People

أو عن طريق ذكر أسماء الحقول :

Select ID, FirstName, LastName, Address From People

ليس بالضرورة أن نستورد جميع الحقول فإذا أردنا مثلاً أن نستورد الإسم والكنية من كل سجل ؟

Select FirstName, LastName From People

الشرط في الإستعلام :

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

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

لديك جدول يحوي خمسمائة وأربعين ألف سجل لأشخاص تعرفهم ومن هذه السجلات لديك مايعادل 40% لأشخاص يحملون إسم محمد ومهمتك هي أن تجد عنوان شخص إسمه محمد لكن الكنية غير معروفة وكل ماتذكره عن هذا الشخص أن اسمه محمد وكنيته تبدأ بحرف الميم ( م )، ستقول لي سأحضر الجدول ومن ثم أبحث عن الأسماء التي تبدأ بحرف الـ( م ) ومن ثم ادقق بالسجلات التي تحمل إسم محمد و أقوم بقراءة كل كنية تبدأ بحرف الـ( م ) تابعة لشخص يدعى محمد، سيساعدني ذلك على التذكر .

طيب ماذا ستفعل إن كانت الأسماء غير مرتبة وعشوائية ؟

هممممممممممممممم، يعني أعمل إيه ؟ سأدقق جميع السجلات.

كم ستحتاج من وقت لإتمام السجلات وإيجاد عنوان الشخص المطلوب ؟!!!!!

اعتقد أني قادر على إنهاء هذا الشيء بيوم واحد :)

ماذا إن اختصرت هذا الشيء بعشر دقائق ؟

لكن كيف ؟

Select FistName, LastName, Address From People Where FirstName = 'Mohammad' And LastName Like 'M%'

دقيقة لوسمحت !!

تذكرت أن مُعرفه الخاص ( 100321 ) !!

كم أحتاج من الوقت لمعرفة عنوانه ؟!!

الجواب ( أجزاء من جزء الثانية !! ) والإستعلام سيكون بسيط جداً :

ٍSelect Address From People Where ID = '100321'

هناك عدة طرق لإنشاء شرط أو شروط معينة للحصول على الإستعلام الأمثل :

الرمز : ( = )]

العمل : ( التأكد من تساوي القيم )

مثال :

FirstName = 'Bashar'

ملاحظات : ( لاشيء )

[[b

الرمز ( < أو !> )]

العمل : ( التأكد من أن قيمة ما أصغر من قيمة معينة )

مثال :

ID < 5

ملاحظات : ( بالنسبة للحقول النصية يتم المقارنة بالترتيب الأبجدي وبالنسبة للتاريخ حسب الفرق . )

[b

الرمز : ( > أو !< )]

العمل : ( التأكد من قيمة ما أكبر من قيمة معينة )

مثال :

ID > 10000

ملاحظات : ( بالنسبة للحقول النصية يتم المقارنة بالترتيب الأبجدي وبالنسبة للتاريخ حسب الفرق . )

[b

الرمز : ( <= )]

العمل : ( التأكد من أن قيمة ما أصغر أو تساوي قيمة معينة )

مثال :

ID <= 99

ملاحظات : ( بالنسبة للحقول النصية يتم المقارنة بالترتيب الأبجدي وبالنسبة للتاريخ حسب الفرق . )

[b

الرمز : ( >= )]

العمل : ( التأكد من أن قيمة ما أكبر أو تساوي قيمة معينة )

مثال :

 FirstName >= 'Mohammad'

ملاحظات : ( بالنسبة للحقول النصية يتم المقارنة بالترتيب الأبجدي وبالنسبة للتاريخ حسب الفرق . )

[b

الرمز ( <> أو != )]

العمل : ( التأكد من قيمة ما لاتساوي قيمة معينة )

مثال :

LastName <> 'Gates'

ملاحظات : ( لاشيء )

[b

مع استخدام الكلمة المحجوزة ( Like ) :

الرمز : ( % )]

العمل : ( عدة استخدامات لكن جميعها يعتمد على أي مزيج من الأحرف )

مثال عن ( أي قيمة نصية تبدأ بمقطع نصي معين ) :

FirstName Like 'B%'

ملاحظات : ( أي نص يبدأ بحرف الـ( B ) )

مثال عن ( أي قيمة نصية تنتهي بمقطع نصي معين ) :

FirstName Like 'at%'

ملاحظات : ( أي نص ينتهي بالحرفين ( at ) )

مثال عن ( أي قيمة نصية تحوي مقطع نصي معين ) :

FirstName Like '%VS%'

ملاحظات : ( أي نص يحوي الحرفين ( VS ) )

[b

الرمز : ( _ )]

العمل : ( تعويض عن حرف مفقود )

مثال :

FirstName Like 'Bash_r'

ملاحظات : ( أي نص شبيه النص المذكور ( Bash_r ) مثل ( BashAr ) و ( Bashar ) و ( BashBr ) و ( Bashbr ) الخ ... )

[b

"]

العمل : ( عدة استخدامات لكن جميعها يعتمد على أي مجموعة من الأحرف )

مثال عن ( مجموعة من الأحرف ) :

LastName Like '[a-g]bd'

ملاحظات : ( اي قيمة نصية تبدأ بالأحرف من الـ( a ) الى الـ( g ) وتنتهي بـ( bd ) )

مثال عن ( مجموعة محددة من الأحرف ) :

FirstName Like '[sr]ami'

ملاحظات : ( أي قيمة نصية تبدأ بإحدى الحرفين ( S ) أو ( R ) وتنتهي بـ( ami ) )

الرمزين : [

"]

العمل : ( عدة استخدامات لكن جميعها يعتمد على أي مجموعة من الأحرف )

مثال عن ( لا تحوي مجموعة من الأحرف ) :

LastName Like '[^a-g]bd'

ملاحظات : ( عكس النحو ( [ ] ) بالنسبة لمجموعة من الأحرف )

مثال عن ( لاتحوي مجموعة محددة من الأحرف ) :

FirstName Like '[^hz]mar'

ملاحظات : ( عكس النحو ( [ ] ) بالنسبة لمجموعة محددة من الأحرف )

الرموز : [ ^

التأكد من وجود قيمة حقيقة بالخلية :

الجملة : ( Is Null )]

العمل : ( التأكد من قيمة ما تساوي لاشيء بمعنى أن المستخدم لم يدخل قيمة لهذه الخلية )

مثال :

FirstName Is Null

ملاحظات : ( يستخدم هذا النوع من الشرط في حال الإستعلام عن سجلات لاتحوي قيمة للخلية المذكورة في الشرط )

[b

الجملة : ( Is Not Null )]

العمل : ( التأكد من قيمة ما تساوي شيء بمعنى أن الخلية تم إعداد قيمتها مسبقاً )

مثال :

LastName Is Not Null

ملاحظات : ( يستخدم هذا النوع من الشرط لإستيراد السجلات التي تحقق شرط ( أن الخلية لها قيمة ) )

[b

اختيارية :

حرف الجر : ( In )]

العمل : ( التأكد من أن قيمة ما تساوي إحدى القيم المذكورة بين قوسين بعد الحرف ( In ) )

مثال :

City In ('Damascus', 'Aleppo)

ملاحظات : ( لاشيء )

[b

حرف الجر : ( Between )]

العمل : ( التأكد من أن قيمة ما تساوي إحدى القيم بين القيمتين بعد الحرف ( Between و And ) )

مثال :

Salary Between 25000 And 40000

ملاحظات : ( لاشيء )

[b

وأخيراً نأتي إلى جمع الشروط ، والمقصود هنا هو التأكد من عدة شروط باستخدام العبارات المنطقية ( AND, OR, NOT ) :

العبارة : ( And ) أي ( و )]

مثال :

( (FirstName = 'Bashar' And LastName = 'Rabatt') )

[b

العبارة : ( Or ) أي ( أو )]

مثال :

(FirstName = 'Mohammad' Or FirstName = 'Ahmad')

[b

العبارة : ( Not ) أي ( ليس )]

مثال :

Not (Profession = 'Programmer' And Age > 40)

[b

الترتيب في الإستعلام :

حسناً، ماهو الترتيب ؟

الترتيب كما نعرف جميعاً أنه إعداد مجموعة من نصوص أو الأرقام أو تواريخ بشكل تصاعدي أو تنازلي منسق لكن هذا بالنسبة لحياتنا العملية فبالنسبة للحياة البرمجية هناك عدة طرق لتنسق جدول والمقصود ( بعدة طرق ) هنا هو أن كل حقل من جدول يخولك أن تقوم بترتيبه بطريقتان ( تصاعدي، تنازلي ) وعلى فرض أنه لدينا جدول بعشر حقول فمجموع طرق عرض تنسيق الجدول ستكون ( 10 ^ 2 )=( 100 ) طبعاً الإعتماد يتم على اختلاف محتويات الجدول لأنه وعلى فرض أن كل حقل من حقول الجدول تحمل عدد كبير من الخلايا المتشابهة ؟ كلما زادت الخلايا المتشابهة، قلت طرق عرض التنسيقات وليس بمعنى أنك غير قادر على كتابة أسماء الحقول وإنما ستكون الخلايا متشابهة الأماكن في العرض حسب الترتيب المذكور في الإستعلام .

نأتي الأن للكلمة المحجوزة ومايجب استخدامه مع هذه الكلمة :

Order By <ColumnName> ASC | DESC

Order By : هي الجلمة المحجوزة التي تخبر الإستعلام أننا نريد ترتيب الجدول .

<ColumnName> : يجب أن نعوض هذا النص بقيمة اسم الحقل .

ِASC : والتي تَختصر ( Ascending ) والمقصود ( ترتيب تصاعدي )=( من الصغير إلى الكبير )=( 1، 2، 3، 4، 5 )

DESC : والتي تَختصر ( Descending ) والمقصود ( ترتيب تنازلي )=( من الكبير إلى الصغير )=( 5، 4، 3، 2 ،1 )

أمثلة على ماسبق :

ترتيب الجدول بالنسبة للحقل ( FirstName ) بشكل تصاعدي :

ٍSelect
*
From
People
Order By
FirstName ASC

ترتيب الجدول بالنسبة للحقل ( FirstName ) و ( LastName ) بشكل تصاعدي :

Select
*
From
People
Order By
FirstName ASC,
LastName ASC

أو بإسناد رقم الحقل عوضاً عن إسمه :

Select
*
From
People
Order By
2 ASC,
3 ASC

لنرى مثال عن استخدام جميع الكلمات المحجوزة السابقة :

ٍSelect
*
From
People
Where
FirstName Like 'B%'
Order By
FirstName ASC,
LastName ASC

|_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_|

نبدأ الأن مع الإجراءات الأساسية وهي :

Insert, Delete, Edit

* Insert أو ( إدخال )

يخولك هذا الإجراء من إدخال سجل جديد في جدول محدد .

مطالب الإجراء ( اسم الجدول ) - ( الخلايا التي سيتم إعداد قيمها ) - ( قيم الخلايا المذكورة )

شكل جملة الإدخال :

Insert Into <TableName>
(
<Column1>,
<Column2>,
<Column3>
)
Values (<Value1>, <Value2>, <Value3> )

لنأخذ مثال عملي على جدول الأشخاص :

Insert Into People
(
FirstName,
LastName,
Address
)
Values ( 'Ahmad', 'Al-Hindi', 'Unknown' )

* Update أو ( تعديل )

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

مطالب الإجراء ( اسم الجدول ) - ( الخلايا التي سيتم تعديل قيمها ) - ( قيم الجديدة للتعديل )

شكل جملة التعديل :

Update <TableName>
Set
<Column1> = <Value1>,
<Column2> = <Value2>,
<Column3> = <Value3>
Where
<Predicate>

مثال عملي على جدول الأشخاص، المثال التالي سيعدل جميع السجلات التي قيمة خلية الاسم الأول منها تساوي ( Ahmed ) باستبدال هذه القيمة بـ( Ahmad ) :

Update People
Set
FirstName = 'Ahmad'
Where
FirstName = 'Ahmed'

* Delete أو ( حذف )

يستخدم هذا الإجراء لحذف سجل أو عدة سجلات، ينصح بتأني عند استخدامه وذلك بالتأكد من جملة الشرط المكتوب تحت الكلمة ( Where )، فإذا لم هناك شرط ؟ سيتم مسح جميع السجلات ! وإذا كان هناك تكرار؟ سيتم مسح كل سجل يحوي قيمة تحقق شرط من الشروط المذكورة في الإستعلام ! ( لذلك انتبه جيداً ;) ) .

مطالب الإجراء ( اسم الجدول ) - ( شرط الحذف )

شكل جملة الحذف :

Delete From <TableName>
Where <Predicate>

مثال عملي على جدول الأشخاص، سنقوم بحذف جميع سجلات الأشخاص التي كنيتهم ( Abo Lamba ) :

Delete From People
Where LastName = 'Abo Lamba'

في الدرس القادم سنرى الأنواع التي يدعمها الـ( SQL ) وكيفية التقيد بأنواع محددة للحصول على أداء أسرع وتوفير أكبر في ذاكرة التخزين، وأيضاً سنبدأ بدراسة الـ( ADO.NET ) .

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

بنظري أن برمجة قواعد البيانات هي أسهل شيء يمكن أن يمر على مبرمج، ولاتحتاج الى تفكير عميق كما يظن البعض منا لكن ذلك لايعني أنها لاتحتاج للتفكير و التخطيط !، بشكل عام ( برمجة قواعد البيانات تعتمد على التخطيط أو الرسم البياني )=( فلا تحاول أن تبدأ بمشروع كبير قبل أن ترسم له مخطط بياني ! ;) )

بالتوفيق :) .

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

شكرا لك اخي بشارِ على هذه المقدمة الموفقة بشرح التعامل مع قواعد البيانات :lol: , اذا كنت تريد مساعدة في شرح بعض الفصول فانا جاهز ليس نقصا في معرفتك و لكن

طبقا للمثل القائل " الحمل اذا بيتقسم بيتشال" , عموما هل باب الاسالة مفتوح اريد ان اسال سؤال خطر على بالي منذ فترة , و هو على بساطته لم استطع الاجابة عليه ,

ام ان باب الاسالة لم يفتح بعد , انما تريد انهاء الدرس و بعد ذلك تفتح باب الاسالة. :o

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

تم تثبيت الموضوع

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

السلام عليكم ورحمه الله وبركآته .. ,

بارك الله فيك ..

/

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
السلام عليكم و رحمة الله و بركاته

شكرا لك اخي بشارِ على هذه المقدمة الموفقة بشرح التعامل مع قواعد البيانات :lol: , اذا كنت تريد مساعدة في شرح بعض الفصول فانا جاهز ليس نقصا في معرفتك و لكن

طبقا للمثل القائل " الحمل اذا بيتقسم بيتشال" , عموما هل باب الاسالة مفتوح اريد ان اسال سؤال خطر على بالي منذ فترة , و هو على بساطته لم استطع الاجابة عليه ,

ام ان باب الاسالة لم يفتح بعد , انما تريد انهاء الدرس و بعد ذلك تفتح باب الاسالة. :o

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

تم تثبيت الموضوع

شكراً :) :wub:

السلام عليكم ورحمه الله وبركآته .. ,

بارك الله فيك ..

وبارك فيكم جميعاً :)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

طيب , سؤالي هو في جملة الاستعلام تطر أحيانا للبحث عن طريق الاسم في حقل معين , و الاسم المدخل نستطيع البحث عنه بدون مشاكل

كالتالي

  
Select
*
From
People
Where
FirstName Like 'Mohammad%'

ولكن اذا كانت كلمة Mohammad هذه التي في جملة الـ Where Condition مدخلة بهذه الصيغة Moh'd

فلن نتمكن من البحث عنها لأنه يرجع خطأ و ذلك لعدم قبول جملة الـ Where Condition بهذه الصيغة

  
Select
*
From
People
Where
FirstName Like 'Moh'd%'

طبعا يجب ان تترك حرية طريقة الادخال لليوزر , و ايضا يجب ان تترك له الحرية في البحث ان يكتب ما يشاء

باعتقادي ان الصورة و صلت لذلك ما ردك يرعاك الله

تم تعديل بواسطه assaf_abdullah
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بما أنى متواجد فسأجيب عليك أخى عبدالله بعد إذنك أخى بشار

يجب عليك استبدال علامة ' بعلامتين منها أى ''

   Select
*
From
People
Where
FirstName Like 'Moh''d%'

تم تعديل بواسطه GHOST2010
0

شارك هذا الرد


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

يجب عليك استبدال علامة ' بعلامتين منها أى ''

   Select
*
From
People
Where
FirstName Like 'Moh''d%'

خود راحتك يامعلم ( مشكور :) )

هو دا ;)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ما شاء الله عيكما :blush: اخجلتماني ما اتوقعت ان الامور بهذه البساطة , شكرا لكما.

سالت عدة مبرمجين من اصدقائي و لم يجاوبني احد , ماشاء الله عليكما.

تم تعديل بواسطه assaf_abdullah
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

أنواع الكائنات المدعومة في الـ( SQL )

قلنا في الدرس السابق أننا سنرى الأنواع التي يدعمها الـ( SQL ) وقلنا أيضاً أننا سنتقيد بأنواع محددة للحصول على الأداء الأفضل والتوفير الأكبر في التخزين، لكن كيف ؟

من المعروف أن كل نوع من الأنواع الموجودة في الـ( Visual Basic.NET ) تحجز حجم معين من البت ( bit ) في الذاكرة، كل ( 8 Bit ) تشكل ( 1 Byte ) البت عبارة عن نوع منطقي يمثل القيمتين ( الصفر ) و ( الواحد ) أي كالـ( Boolean ) في الـ( Visual Basic.NET ) والذي يمكن أن يحوي إحدى القيمتين التاليتين ( False, True ) والـ( Bit ) هو جزء من صيغة النظام الثنائي فكل خانة من خانات عدد بالنظام الثنائي تشكل ( Bit ) وعلى سبيل المثال الحرف ( A ) الذي يمثل الرمز ( 65 ) من جدول الـ( ASCII )، جدول الـ( ASCII ) يحوي 255 رمز ويمكن تمثيل مكان أي رمز من جدول الـ( ASCII ) بالـ( Byte ) :

ASCII( 65 ) = A

و

ASCII( A ) = 65

الفكرة من عرض هذه البيانات هو أن نرى كيف يتم تخزين البيانات وكيف يتم احتساب حجم كل كائن، القيمة ( 65 ) والتي يمكن أو يجب أن تمثل بـ( Byte ) لسبب أن حد الـ( Byte ) الأدنى ( 0 ) وحده الأعظم ( 255 ) ولايحجز إلا ( 8 بت ) من ذاكرة التخزين فهو الأفضل بالنسبة لهذه القيمة. الثمانية بت هي عبارة عن ثمانية قيم من ( 0 و 1 ) لأن الحاسب لايفهم إلا هذه اللغة :) :

65 = 1000001

1000001 = 65 = A

الأن لنرى الأنواع التي يدعمها الـ( SQL ) ومقابلتها في الـ( Visual Basic.NET ) ووصف عن عملها أو طبيعة استخدامها، وصيغة عن قيمتها إن كان بالإمكان عرضه :

post-178281-1254413487_thumb.jpg

post-178281-1254411342_thumb.jpg

post-178281-1254411427_thumb.jpg

post-178281-1254411365_thumb.jpg

post-178281-1254411460_thumb.jpg

post-178281-12605560162126_thumb.jpg

الدرس المقبل سيكون عن الـ( ADO.NET ) تعريف واستخدام :)

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ADO.NET

أسماء الفضاء :

System.Data : يحوي واجهات ( Interfaces )، صفوف ( Classes )، مرقمات ( Enumerations ) وندوبين ( Delegates ) خاصة بمطالب قواعد البيانات .

System.Data.Common : يحوي صفوف مزودات قواعد البيانات ( Data Providers ) .

System.Data.Design : أيضاً يحوي صفوف لكن هذه الصفوف مختصة بتعديل الكائن ( DataSet ) والمقصود بتعديل هو توليد ( DataSet ) حسب الطلب ( الاحتياجات ) .

System.Data.Odbc : مزود بيانات الـ( Odbc ) .

System.Data.OleDb : مزود بيانات الـ( OleDb ) .

System.Data.Sql : يحوي صفوف تدعم وظائف الـ( SQL Server ) المعينة أو المتقدمة .

System.Data.OracleClient : مزود بيانات الـ( Oracle ) .

System.SqlClient : مزود بيانات الـ( SQL Server ) .

System.SqlServerCe : مزود بيانات الـ( SQL Server ) الخاص بالجوال ( Mobile ) .

System.Data.SqlTypes : صفوف للأنواع التي يدعمها الـ( SQL Server )، تكلمنا عنها في درسنا السابق :) .

Microsot.SqlServer.Server : يحوي مكونات يمكن أن تدمج أو تكمل الـ( SQL Server ) والـ( CLR ) .

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

تكلمنا في درسنا الأول عن جدول يحوي معلومات أشخاص كالـ( المُعرف والذي رمزنا له بـ[ ID ]، الاسم والذي رمزنا له بـ[ FirstName ]، الكنية رمزنا لها بـ[ LastName ]، وأخيراً العنوان والذي رمزنا له بـ[ Address ])، هذا الجدول بسيط ولايحتاج إلى مخطط بياني والسبب أن ليس هناك من علاقات تصله بجداول أخرى وليس هناك من عمليات حسابية تتبع خوارزمية معينة، إذا فهو لايحتاج إلى مخطط بياني :)، لكن قواعد البيانات المتقدمة والتي تحوي علاقات وإجراءات مخزنة وعمليات فرعية تحتاج بالفعل إلى مخطط بياني، الهدف من هذا المخطط هو عرض الخوارزمية المستخدمة في تشكيل القاعدة استعلاماً وربطاً وتسهيل عملية فهم مبدء عمل هذا التطبيق أو عناصر قاعدة البيانات، المهم من هذا الحديث أن الـ( ADO.NET ) أيضاً له مخطط يعمل به :

post-178281-1254517938_thumb.jpg

العناصر الرئيسية في الـ( ADO.NET ) هي :

-> Provider : مزود البيانات والذي بدوره يقوم بالإتصال بمصدر بيانات تابع لمحرك من محركات قواعد البيانات أي ( SQL Server, ODBC, MySql, OleDb, Oracle ) ويقوم بمعالجة البيانات حسب فئتها ليتم استخدامها عن طريق :

-->DataAdapter : يخولك هذا الكائن من التعامل مع البيانات على شكل جداول ويخولك أيضاً من ( قراءة، تعديل، حذف ) بيانات الجدول بشكل مباشر عام .

-->DataReader : والذي يخولك قراءة البيانات على هيئة فردية ( كل سجل على حده ) .

-> Dataset : يستخدم هذا الكائن للتعامل مع البيانات بشكل مستقل أي يتم قراءة كل البيانات المطلوبة في الذاكرة ومن ثم يتم قطع الاتصال بقاعدة البيانات، ويبقى عملك محصور ببيانات الـ( Dataset ) المخزنة في الذاكرة اي كل ماتقوم بـ( إضافته، تعديله، حذفه ) ينفذ على البيانات المخزنة في الـ( Dataset ) اي في الذاكرة، لايحبذ استخدام هذا النوع من المعالجة في حال كانت البيانات المستوردة من قاعدة البيانات إلى الـ( Dataset ) بحجم كبير والسبب أن هذا الحجم سيكون محجوز في الذاكرة مماسيؤدي إلى تخفيض مستوى الذاكرة المتوفرة وتبطيء أداء النظام .

نرى من المخطط السابق أن مصدر البيانات بالنسبة للـ( Dataset ) يمكن أن يكون إما ( Database ) أو ( XML ) ومن أسهم الربط نفهم أننا قادرين على إرسال واستقبال البيانات من إحدى المصدرين ،لكن بالنسبة للـ( XML ) فليس هناك حاجة لاستخدام الـ( DataAdapter ) لقراءة هذه اللغة وتحويل محتوياتها إلى ( جداول->حقول وسجلات )، وبالمناسبة يمكننا كتابة البيانات المستوردة من ( Database ) باستخدام الإجراء ( WriteXML ) التابع للـ( Dataset ) في ملف ( XML ) أو في حقل من نوع ( XML ) ليتم قراءة البيانات في ( Dataset ) عبر العملية ( ReadXml ) من الـ( Dataset ) نفسها أو يمكننا قراءة المحتوى من ملف خارجي .

الأن نعود إلى درسنا لنفهم مبدء تعدد المزودات ( Providers )، لاحظنا من أسماء الفضاء اي الـ( Name spaces ) أنه يوجد عدة مزودات منها :

OleDb : يمكننا استخدامه مع أي نوع من المحركات ويعد شامل بالنسبة لأنواع محركات البيانات المدعومة من قِبل مايكروسوفت ( Microsoft ) .

SqlClient : يستخدم مع قواعد بيانات الـ( SQL ) وبما أنه مخصص للـ( SQL) فبالطبع يساعدك على التفريق بين الاتصالات الأخرى ويعطي أداء أفضل مع قواعد البيانات خاصته ( ملاحظة لايمكن استخدام هذا المزود مع قواعد بيانات الـ( SQL) ذو النسخة ( 6.5 ) والأقدم من رقم النسخة المذكورة ) .

OracleClient : يستخدم مع قواعد بيانات الـ( Oracle ) وبنفس السبب السابق للـ( SQL) فإنه أداء هذا المزود أفضل من أداء المزود ( OleDB ) مع قواعد بيانات الـ( Oracle ) .

يأتينا سؤال يطرح نفسه - هل هناك من حاجة لاستخدام مزود الـ( OleDB ) في أوقات أو مشارع محددة، هل له فوائد ؟

الجواب، كل شيء في هذه الحياة له فوائد :)، فعلى سبيل المثال يمكننا استخدام هذا المزود للاتصال بقاعدتين بيانات تابعتين لمحركين مختلفين وعلى سبيل المثال ( SQL و Oracle ) وأيضاً يدعم النسخ القديم من الـ( SQL ) ( جميع النسخ ) بمافيها النسخة ( 6,5 ) وماقبلها ;) .

لنرى الفرق بين المزودين الـ( SQL Server ) والـ( Ole DB ) :

post-178281-1254518224_thumb.jpg

لاحظ أن الـ( SQL Server ) يتصل بشكل مباشر بالخادم عبر نظام الشبكة المحلية الخاص به، أما الـ( OleDb ) يحتاج عبور عدة الطبقات لإنشاء اتصال بالـ( SQL ) والسبب كما رأينا في المخطط السابق أن الـ( OleDb ) يحاول جمع المعلومات عن اسم المزود المدرج في نص الإتصال أي ( ConnectionString ) .

ملاحظة : ( يمكن أيضاً جمع بيانات قاعدتين تابعتين لمحركين مختلفين في ( Dataset ) وباستخدام مزودين من مزودات الـ( ADO.NET ) . )

تمثيل سريع عن جمع البيانات من قاعدتين مخلتفتين المزود في ( Dataset ) :

post-178281-1254518028_thumb.jpg

كفانا حديثاً عن المزودات الأن :) لنبدأ بالتعرف عليّهم وكيفية استخدامهم !

( Sql Client ) مزود قواعد بيانات الـ( SQL )

أسماء الفضاء التابعة له :

SqlCommand: يستخدم لتنفيذ استعلام أو عملية من عمليات ( الإضافة [Insert]، التعديل [Update]، الحذف [Delete] ) أو يمكن تنفيذ إجراء مخزن ( Stored Procedure ) من قاعدة البيانات .

SqlConnection : يمثل اتصال الى قاعدة بيانات من الـ( SQL ) .

SqlDataAdapter : يمثل جسر بين ( Dataset أو DataTable ) و مصدر بيانات .

SqlDataReader : يستخدم هذا الكائن لقراءة سجلات بشكل فردي أي ( كل سجل على حده ) التعامل مع هذا الكائن شبيه بالكائن ( Stream ) وللعلم أن هذا الكائن يقرأ بشكل متسلسل إلى الأمام ولايمكن إعادة قراءة البيانات التي تم قرأتها مسبقاً .

SqlError : لاستفسار عن الأخطاء والتحذيرات التي يتعرض أو يصدرها الـ( SQL Server ) .

SqlException : يستخدم ضمن جملة المحاولة ( Try, Catch SqlEx As Exception, End Try ) لعرض أو الاستفسار عن الأخطاء أو التحذيرات التي تطرأ في حال وجوب الجملة ( Try ) في خطأ أو تحذير من الخادم .

SqlParameter : يمكن استخدام هذا الكائن مع الـ( SqlCommand )، يساعدك على تنظيم على تنفيذ العمليات أو الإجراءات المخزنة بطريقة مثالية والتي تتم عبر تحديد اسم المعامل واسم العامود التابع له ونوعه وحجمه، إذا لم تفهمه مبدئياً فهذا شيء عادي لأنه يحتاج إلى تمثيل برمجي ولاحقاً سوف نفعل ذلك ;) .

SqlTransaction : تنفيذ صفقة تحوي عدة عمليات، عند فشل إحدى العمليات تفشل الصفقة بشكل كامل وعند العكس تنجح الصفقة بشكل كامل .

SqlTypes : والذي يحوي الأنواع المدعومة من قِبل الـ( SQL )، تكلمنا عن هذه الأنواع وكيفية التقيد باستخدامها في الدرس السابق .

لنبدأ بمشروع مزود الـ( SQL ) اي الـ( SqlClient ) :

' استدعاء مرجع البيانات الذي يختص بالتعامل مع قواعد البيانات
Imports System.Data
' ( SQL )استدعاء مرجع مزود السكيول وذلك لأننا سنتعامل مع قاعدة بيانات تابعة لمحرك الـ
Imports System.Data.SqlClient

Public Class Form1
' تصريح مغيّر نصي والذي سوف يمثل معلومات الإتصال بقاعدة البيانات
Protected _ConnectionString As String = "Server = .\SQLExpress;" & _
"Integrated Security = True;Database = Northwind"

Private Sub Form1_Load(Byval Sender As Object, _
Byval E As System.EventArgs) Handles MyBase.Load
' الاستدعاء التالي يستخدم لإنشاء صندوق نص كي يتم عرض البيانات فيه
Dim Txt As TextBox = CreateTextBox("TextBoxInfo")
Me.Controls.Add(Txt)
' الصيغة التالية تستخدم لعرض البيانات بشكل منظم لا تشغل بالك بها
Dim CFormat As String = "{0} | {1}"

' ركز الأن;)
' تصريح اتصال سكيول ليتم اتصال بقاعدة البيانات عبره
Dim _SqlConnection As New SqlConnection(_ConnectionString)
' تصريح متغيّر نصي لتمثيل جملة الاستعلام ضمنه
Dim _CommandText As String = "Select * From Employees"
' تصريح أمر سكيول لتنفيذ جملة الاستعلام عبره
Dim _SqlCommand As New SqlCommand( _CommandText, _SqlConnection)

' استخدام جملة المحاولة لتخطي إغلاق أو تجميد التطبيق في حال حدوث خطأ ما
Try
' استخدام الإجراء فتح للاتصال بقاعدة البيانات وجعل حالة الاتصال نشطة
_SqlConnection.Open()
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader()
Txt.Text = String.Format(CFormat, "First Name".PadRight(15), "LastName")
With _SqlDataReader
While .Read
Txt.Text &= (Chr(13) & Chr(10)) & String.Format(CFormat, _
.Item(0), .Item("LastName"))
End While
End With
Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlCommand.Dispose()
_SqlConnection.Close()
End Try
End Sub


' العملية التالية ليس لها دخل في درسنا هذا ومهمتها هي إضافة صندوق نص إلى النموذج كي _
' يتم عرض البيانات المقروئة ضمنه
Private Function CreateTextBox(Byval TextBoxName As String) As TextBox
Dim Txt As New TextBox
With Txt
.Name = TextBoxName
.Text = String.Empty
.MultiLine = True
.Dock = DockStyle.Fill
End With
Return Txt
End Function

End Class

مثال عن قراءة البيانات ضمن جدول باستخدام الـ( SqlDataAdapter ) :

' استدعاء مرجع البيانات الذي يختص بالتعامل مع قواعد البيانات
Imports System.Data
' ( SQL )استدعاء مرجع مزود السكيول وذلك لأننا سنتعامل مع قاعدة بيانات تابعة لمحرك الـ
Imports System.Data.SqlClient

Public Class Form1
' تصريح مغيّر نصي والذي سوف يمثل معلومات الإتصال بقاعدة البيانات
Protected _ConnectionString As String = "Server = .\SQLExpress;" & _
"Integrated Security = True;Database = Northwind"

Private Sub Form1_Load(ByVal Sender As Object, _
ByVal E As System.EventArgs) Handles MyBase.Load
' الاستدعاء التالي يستخدم لإنشاء آداة عرض الجداول كي يتم عرض البيانات فيها
Dim DGV As DataGridView = CreateDataGridView("TextBoxInfo")
Me.Controls.Add(DGV)
' ركز الأن;)
' تصريح اتصال سكيول ليتم اتصال بقاعدة البيانات عبره
Dim _SqlConnection As New SqlConnection(_ConnectionString)
' تصريح متغيّر نصي لتمثيل جملة الاستعلام ضمنه
Dim _CommandText As String = "Select FirstName, LastName From Employees"
' ( SqlDataAdapter ) تصريح كائن الوصل اي
Dim _SqlDataAdapter As New SqlDataAdapter(_CommandText, _SqlConnection)
' استخدام جملة المحاولة لتخطي إغلاق أو تجميد التطبيق في حال حدوث خطأ ما
Try
' استخدام الإجراء فتح للاتصال بقاعدة البيانات وجعل حالة الاتصال نشطة
_SqlConnection.Open()
' تصريح جدول جديد ليتم تخزين البيانات المستوردة فيه
Dim _DataTable As New DataTable
' استدعاء العملية ( ملء ) من كائن الوصل ليتم ملء البيانات بالجدول المصرح
_SqlDataAdapter.Fill(_DataTable)
DGV.DataSource = _DataTable
Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlDataAdapter.Dispose()
_SqlConnection.Close()
End Try
End Sub

' العملية التالية ليس لها دخل في درسنا هذا ومهمتها هي إضافة آداة عرض الجداول إلى النموذج كي _
' يتم عرض البيانات المستوردة فيها
Private Function CreateDataGridView(ByVal DataGridViewName As String) As DataGridView
Dim DGV As New DataGridView
With DGV
.Name = DataGridViewName
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.Dock = DockStyle.Fill
End With
Return DGV
End Function

End Class

( OleDb ) مزود قواعد بيانات شامل للمحركات المدعومة من قبل ( Microsoft )

أسماء الفضاء :

OleDbCommand : نفس شرح الـ( SqlCommand )

OleDbConnection : يمثل اتصال الى قاعدة بيانات، يتم تحديد محرك قواعد البيانات في معلومات الاتصال، شرح بعض اختصارات المزودات ( أسماء المحركات ) :

* DB2OLEDB : يستخدم مع الـ( DB2 )

* SQLOLEDB : يستخدم مع الـ( SQL Server )

* Microsoft.Jet.OLEDB.4.0 : يستخدم مع الـ( Access )

* MSDAORA : يستخدم مع الـ( Oracle )

* MSDASQL : يستخدم مع الـ( OBDC )

OleDbDataAdapter : نفس شرح الـ( SqlDataAdapter )

OleDbDataReader : نفس شرح الـ( SqlDataReader )

OleDbError : نفس شرح الـ( SqlError ) لكن من الممكن أن يختلف المزود الذي يبعث بالخطأ أو التحذير

OleDbException : نفس شرح الـ( SqlException ) مع تغير جملة المحاولة إلى ( Try, Catch OleDBEx As OleDbException, End Try )

OleDbParameter : نفس شرح الـ( SqlParameter ) لكن يجب استخدام هذا الكائن مع الـ( OleDbCommand )

OleDbTransaction : نفس شرح الـ( SqlTransaction )

OleDbTypes : هناك بعض الاخلافات والتي تمثل بـ( Object ) في الـ( Visual Basic.NET )

الاستخدام حقيقةً لايختلف كثيراً فكما ذكرنا أن معلومات الاتصال يجب ان تحدد وجهتها والمقصود ( مالمحرك المطلوب لهذا الاتصال ) وهاهو الفرق الوحيد :)، طبعاً بالنسبة للأنواع فيجب أيضاً التقيد بالفئة أي يجب استخدام أنواع الـ( OleDb ) في تصريح المعاملات اي الـ( Parameters )

لنرى الفرق الوحيد بين المزودين ( لكن تذكر مقلناه : كل مزود يدعم محركه بشكل أفضل من الـ( OleDb )) والأن :

' استدعاء مرجع البيانات الذي يختص بالتعامل مع قواعد البيانات
Imports System.Data
' استدعاء مرجع مزود الـ( او ال اي دي بي ) ليتم استخدام عناصره
Imports System.Data.OleDb

Public Class Form1
' تصريح مغيّر نصي والذي سوف يمثل معلومات الإتصال بقاعدة البيانات
' ( SQL Server )والذي يرمز إلى الـ ( SQLOleDb ) لاحظ تحديد اختصار المحرك
Protected _ConnectionString As String = "Provider = SQLOleDb;DataSource = .\SQLExpress;" & _
"Integrated Security = SSPI;Initial Catalog = Nothwind"

Private Sub Form1_Load(ByVal Sender As Object, _
ByVal E As System.EventArgs) Handles MyBase.Load
' الاستدعاء التالي يستخدم لإنشاء صندوق نص كي يتم عرض البيانات فيه
Dim Txt As TextBox = CreateTextBox("TextBoxInfo")
Me.Controls.Add(Txt)
' الصيغة التالية تستخدم لعرض البيانات بشكل منظم لا تشغل بالك بها
Dim CFormat As String = "{0} | {1}"

' ركز الأن;)
' تصريح اتصال ( او ال اي دي بي ) ليتم الاتصال بقاعدة البيانات عبره
Dim _OleDbConnection As New OleDbConnection(_ConnectionString)
' تصريح متغيّر نصي لتمثيل جملة الاستعلام ضمنه
Dim _CommandText As String = "Select * From Employees"
' تصريح أمر ( او ال اي دي بي ) لتنفيذ جملة الاستعلام عبره
Dim _OleDbCommand As New OleDbCommand(_CommandText, _OleDbConnection)

' استخدام جملة المحاولة لتخطي إغلاق أو تجميد التطبيق في حال حدوث خطأ ما
Try
' استخدام الإجراء فتح للاتصال بقاعدة البيانات وجعل حالة الاتصال نشطة
_OleDbConnection.Open()
Dim _OleDbDataReader As OleDbDataReader = _OleDbCommand.ExecuteReader()
Txt.Text = String.Format(CFormat, "First Name".PadRight(15), "LastName")
With _OleDbDataReader
While .Read
Txt.Text &= (Chr(13) & Chr(10)) & String.Format(CFormat, _
.Item(0), .Item("LastName"))
End While
End With
Catch OleDbEx As OleDbException
MsgBox(OleDbEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_OleDbCommand.Dispose()
_OleDbConnection.Close()
End Try
End Sub



' العملية التالية ليس لها دخل في درسنا هذا ومهمتها هي إضافة صندوق نص إلى النموذج كي _
' يتم عرض البيانات المقروئة ضمنه
Private Function CreateTextBox(ByVal TextBoxName As String) As TextBox
Dim Txt As New TextBox
With Txt
.Name = TextBoxName
.Text = String.Empty
.MultiLine = True
.Dock = DockStyle.Fill
End With
Return Txt
End Function

End Class

مثال عن قراءة البيانات ضمن جدول باستخدام الـ( OleDbDataAdapter ) :

' استدعاء مرجع البيانات الذي يختص بالتعامل مع قواعد البيانات
Imports System.Data
' استدعاء مرجع مزود الـ( او ال اي دي بي ) ليتم استخدام عناصره
Imports System.Data.OleDb

Public Class Form1
' تصريح مغيّر نصي والذي سوف يمثل معلومات الإتصال بقاعدة البيانات
' ( MS Access )والذي يرمز إلى الـ ( Microsoft.Jet.OLEDB.4.0 ) لاحظ تحديد اختصار المحرك
Protected _ConnectionString As String = "Provider = Microsoft.Jet.OLEDB.4.0;DataSource = FileName.mdb;" & _
"Persist Security Info = True"

Private Sub Form1_Load(ByVal Sender As Object, _
ByVal E As System.EventArgs) Handles MyBase.Load
' الاستدعاء التالي يستخدم لإنشاء آداة عرض الجداول كي يتم عرض البيانات فيها
Dim DGV As DataGridView = CreateDataGridView("TextBoxInfo")
Me.Controls.Add(DGV)

' ركز الأن;)
' تصريح اتصال ( او ال اي دي بي ) ليتم الاتصال بقاعدة البيانات عبره
Dim _OleDbConnection As New OleDbConnection(_ConnectionString)
' تصريح متغيّر نصي لتمثيل جملة الاستعلام ضمنه
Dim _CommandText As String = "Select FirstName, LastName From Employees"
' ( OleDbAdapter ) تصريح كائن الوصل اي
Dim _OleDbDataAdapter As New OleDbDataAdapter(_CommandText, _OleDbConnection)
' استخدام جملة المحاولة لتخطي إغلاق أو تجميد التطبيق في حال حدوث خطأ ما
Try
' استخدام الإجراء فتح للاتصال بقاعدة البيانات وجعل حالة الاتصال نشطة
_OleDbConnection.Open()
' تصريح جدول جديد ليتم تخزين البيانات المستوردة فيه
Dim _DataTable As New DataTable
' استدعاء العملية ( ملء ) من كائن الوصل ليتم ملء البيانات بالجدول المصرح
_OleDbDataAdapter.Fill(_DataTable)
DGV.DataSource = _DataTable
Catch OleDbEx As OleDbException
MsgBox(OleDbEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_OleDbDataAdapter.Dispose()
_OleDbConnection.Close()
End Try
End Sub


' العملية التالية ليس لها دخل في درسنا هذا ومهمتها هي إضافة آداة عرض الجداول إلى النموذج كي _
' يتم عرض البيانات المستوردة فيها
Private Function CreateDataGridView(ByVal DataGridViewName As String) As DataGridView
Dim DGV As New DataGridView
With DGV
.Name = DataGridViewName
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.Dock = DockStyle.Fill
End With
Return DGV
End Function

End Class

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

في الدرس المقبل سنرى كيفية التعامل مع مزود البيانات الـ( ODBC ) :) .

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

بانتظار أسئلتكم ;)

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

آلسلام عليكم ورحمه آلله وبركآته .. ,

شرح أكثر من رآئع و تنسيق جميل ..

بآرك الله فيك ..

وبإنتظآر بقية آلدروس

/

تم تعديل بواسطه إشراقــه فجــر
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

قبل أن نتعرف على الـ( Odbc ) عليّنا في بادىء الأمر أن نرى كيفية إنشاء ( Drivers ) في الحقيقة إنشاء محرك ( Odbc ) يختلف يخطوات الإضافة بحسب المزود التابع له اي ( SQL Server, Access, Oracle, Etc... ) لنرى خطوات الوصول إلى مربع حوار الـ( Data Sources ( Odbc ) ) اي ( مصادر بيانات الـ( Odbc ) ) :

نفتح الـ( Control Panel ) اي ( لوحة التحكم ) :

ننقر على ( Administrative Tools ) أو مايدعى بالعربية بـ( الأدوات الإدراية ) .

post-178281-1254767982_thumb.jpg

ومن هذه العاصر :

post-178281-1254768013_thumb.jpg

ننقر على :

( Data Sources ( Odbc ) ) اي ( مصادر بيانات الـ( Odbc ) ) لعرض نافذة ( Odbc Data Source Administrator ) أو ( إدارة مصادر بيانات الـ( Obdc ) ) .

post-178281-1254768039_thumb.jpg

كما نرى من النافذة أنها تحوي اتصالات لمزودات مختلفة وتحوي أيضاً عدة أزرار وهي ( إضافة [Add]، تعديل [Edit]، تكوين [Configure]) وطبعاً لإضافة اتصال جديد لمزود ما علينا النقر على ( إضافة [Add] )، سيظهر لنا االنافذة التالية :

post-178281-1254768061_thumb.jpg

هذه النافذة تحوي معلومات مزودات الاتصالات المتوفرة على الحاسب وهنا يبدأ قرارنا ( مالامحرك الذي نحتاجه ؟ ) وعلى فرض ( SQL Server ) كما هو محدد بالصورة السابقة، ننقر على ( التالي [Next] ) بعد أن نحدد المزود اي الـ( SQL Server ) .

post-178281-1254768076_thumb.jpg

عليّنا هنا إدخال معلومات الاتصال كالـ( اسم [Name]، وصف [Description]، الخادم أو الملقم [server] ) ومن ثم ننقر على ( Next ) :

post-178281-1254768091_thumb.jpg

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

( عبر الـ( Windows Authentication ) أو عبر الـ( SQL Server Authencation ) )، يمكن التحديد على حسب حاجتك أو على حسب برمجة قاعدة بياناتك .

post-178281-1254768109_thumb.jpg

هنا علينا أن نحدد أي قاعدة بيانات يجب استخدامها بهذا الاتصال ؟

بعد التحديد ننقر على ( التالي [Next] ) .

post-178281-1254768127_thumb.jpg

قم بتغير اللغة لما يتناسب مع الـ( Windows ) خاصتك أو دعه القيمة ( Default ) والتي تمثل اللغة الإفتراضية للجهاز أو قم باختيار اللغة التي تريد عرض رسائل الـ( SQL ) بها .

ننقر على ( التالي [Next] )

post-178281-1254768141_thumb.jpg

يتم هنا عرض معلومات الاتصال الذي قمنا بإعداده، من هذه النافذة علينا النقر على ( اختبار مصرد البيانات [Test Data Source] ) لاختبار حالة الاتصال : هل يعمل أما لا :

post-178281-1254768151_thumb.jpg

كما نلاحظ ( تمت الاختبارات بنجاح! )

أسماء الفضاء أو العناصر التابعة للـ( Odbc ) :

OdbcCommand : يستخدم لتنفيذ استعلام أو عملية من عمليات ( الإضافة [Insert]، التعديل [Update]، الحذف [Delete] ) أو يمكن تنفيذ إجراء مخزن ( Stored Procedure ) من قاعدة البيانات .

OdbcConnection : يمثل اتصال الى محرك من المحركات المتوفرة في الـ( Odbc ) .

OdbcDataAdapter : يمثل جسر بين ( Dataset أو DataTable ) و مصدر بيانات .

OdbcDataReader : يستخدم هذا الكائن لقراءة سجلات بشكل فردي أي ( كل سجل على حده ) التعامل مع هذا الكائن شبيه بالكائن ( Stream ) وللعلم أن هذا الكائن يقرأ بشكل متسلسل إلى الأمام ولايمكن إعادة قراءة البيانات التي تم قرأتها مسبقاً .

OdbcError : لاستفسار عن الأخطاء والتحذيرات التي يتعرض أو يصدرها المزود المستخدم في الـ( Odbc ) .

OdbcException : يستخدم ضمن جملة المحاولة ( Try, Catch OdbcEx As OdbcException, End Try ) لعرض أو الاستفسار عن الأخطاء أو التحذيرات التي تطرأ في حال وجوب الجملة ( Try ) في خطأ أو تحذير من الخادم .

OdbcParameter : يمكن استخدام هذا الكائن مع الـ( OdbcCommand )، يساعدك على تنظيم على تنفيذ العمليات أو الإجراءات المخزنة بطريقة مثالية والتي تتم عبر تحديد اسم المعامل واسم العامود التابع له ونوعه وحجمه، يجب مراعاة النوع لأن الـ( Parameter ) الخاص بالـ( Odbc ) له أيضاً أنواعه الخاصة .

OdbcTransaction : تنفيذ صفقة تحوي عدة عمليات، عند فشل إحدى العمليات تفشل الصفقة بشكل كامل وعند العكس تنجح الصفقة بشكل كامل .

الأن لنرى كيف يمكننا الاتصال بالمحرك الذي تم إنشائه :

ملاحظة : ( إذا كانت قاعدة البيانات تطلب ( اسم مستخدم وكلمة مرور ) فعليّك تضمين الأوسمة التالية لإرسال الاسم وكلمة المرور إلى المحرك، ( "UID = UserName; PWD = Password" ) )

' استدعاء مرجع البيانات الذي يختص بالتعامل مع قواعد البيانات
Imports System.Data
' ( Odbc Data Sources )استدعاء مرجع مزود ( او دي بي سي ) وذلك لأننا سنتعامل مع محرك من المحركات المصرحة في
Imports System.Data.Odbc

Public Class Form1
' ( تصريح مغيّر نصي والذي سوف يمثل معلومات الإتصال بمحرك ( او دي بي سي
Protected _ConnectionString As String = "DNS = MySQLOdbc"

Private Sub Form1_Load(ByVal Sender As Object, _
ByVal E As System.EventArgs) Handles MyBase.Load
' الاستدعاء التالي يستخدم لإنشاء صندوق نص كي يتم عرض البيانات فيه
Dim Txt As TextBox = CreateTextBox("TextBoxInfo")
Me.Controls.Add(Txt)
' الصيغة التالية تستخدم لعرض البيانات بشكل منظم لا تشغل بالك بها
Dim CFormat As String = "{0} | {1}"

' ركز الأن;)
' تصريح اتصال ( او دي بي سي ) ليتم الاتصال بمحرك عبره
Dim _OdbcConnection As New OdbcConnection(_ConnectionString)
' تصريح متغيّر نصي لتمثيل جملة الاستعلام ضمنه
Dim _CommandText As String = "Select * From Employees"
' تصريح أمر ( او دي بي سي ) لتنفيذ جملة الاستعلام عبره
Dim _OdbcCommand As New OdbcCommand(_CommandText, _OdbcConnection)

' استخدام جملة المحاولة لتخطي إغلاق أو تجميد التطبيق في حال حدوث خطأ ما
Try
' استخدام الإجراء فتح للاتصال بالمحرك وجعل حالة الاتصال نشطة
_OdbcConnection.Open()
Dim _OdbcDataReader As OdbcDataReader = _OdbcCommand.ExecuteReader()
Txt.Text = String.Format(CFormat, "First Name".PadRight(15), "LastName")
With _OdbcDataReader
While .Read
Txt.Text &= (Chr(13) & Chr(10)) & String.Format(CFormat, _
.Item(0), .Item("LastName"))
End While
End With
Catch OdbcEx As OdbcException
MsgBox(OdbcEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_OdbcCommand.Dispose()
_OdbcConnection.Close()
End Try
End Sub


' العملية التالية ليس لها دخل في درسنا هذا ومهمتها هي إضافة صندوق نص إلى النموذج كي _
' يتم عرض البيانات المقروئة ضمنه
Private Function CreateTextBox(ByVal TextBoxName As String) As TextBox
Dim Txt As New TextBox
With Txt
.Name = TextBoxName
.Text = String.Empty
.MultiLine = True
.Dock = DockStyle.Fill
End With
Return Txt
End Function

End Class

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

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

نحن فى النتظار وفقك الله

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الاتصالات ( Connections )

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

رأينا في ماسبق أن ( Microsoft ) تدعم بعض المزودات ومنها ( Odbc, OleDb, Oracle, SQL Server, SQL Server CE ) هذه المزودات تابعة تحت اسم الفضاء ( Data ) وبالتالي نفهم أن :

Odbc تابع لـ( System.Data.Odbc )

OleDb تابع لـ( System.Data.OleDb )

Oracle تابع لـ( System.Data.OracleClient )

SQL Server تابع لـ( System.Data.SqlClient )

SQL Server CE تابع لـ( System.Data.SqlServerCe )

الاتصالات بشكل عام تعتمد على معلومات يتم إدراجها عند تصريح الاتصال أو عن طريق إعداد الخصائص بعد إنشاء ( تصريح كائن جديد من نوع ) اتصال تابع لإحدى المزودات .

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

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

كما رأينا في الدروس السابقة أن لتعريف اتصال جديد يتصل بالخادم التابع للـ( SQL ) نحدد ثلاثة أشياء وهي :

الخادم ( Data Source ) تعابير ممائلة يمكن استخدامها عوضاً عن التعبير المذكورة أي ( Data Source ) :

Server ( الخادم الملقم )

Address ( عنوان قاعدة البيانات ) ويمكن اختصاره بـ( Addr )

Network Address ( عنوان الشبكة )

ومع الملاحظة أن جميع العبارات المذكورة تقبل اسم الخادم أي ( sqlexpress\. ) بعد إشارة اليساوي التي تليها ;)، نفهم أن مهما كانت العبارة فهي مجرد عبارة نصية تساعدك على استوعاب جهة الاتصال وبالأحرى القيمة التي تلي إشارة اليساوي ( = ) بعد العبارة المستخدمة في تحديد الخادم، وبالتالي أنت حر ( استخدم ماتجده مثالياً بطريقة اتصالك بالخادم ;) ) .

للتذكير : ( "Server = .\sqlexpress; Integrated Security = True; DataBase = Northwind" )

لنفهم :

في الأمثلة المذكورة في الدروس السابقة قمنا باستخدام الـ( Server ) والذي يسعى للاتصال بخادم الـ( SQL ) الموجود على نفس الحاسب، يجب أن يأتي بعد إشارة اليساوي ( = ) التي تلي كلمة ( Server ) اسم الخادم المراد التعامل معه ( sqlexpress\. ) بالنسبة للنسخة التي أملكها .

وبعد إشارة اليساوي ( = ) التي تلي ( Integrated Security ) قيمة منطقية اي ( True, False ) أو بدائل شبيهة ( Yes, No ) أو اختصار نوع الحماية ( SSPI )، هذه العبارة تخبر الاتصال عن حالة الحماية و التوثيق .

وفي النهاية وبعد إشارة اليساوي ( = ) التي تلي ( Database ) يجب تضمين اسم قاعدة البيانات ( الموجودة ضمن نطاق الخادم ) المراد معالجة بياناتها .

سؤال من الممكن أن تسأله لنفسك إن كنت فضولياً ;)، هل هناك من عبارات أخرى يمكن استخدامها ضمن معلومات الاتصال لإعداد خصائص أخرى ؟

الجواب ( نعم! ) ومنها :

Application Name : ليس هناك شي يفيدنا ( للمعرفة ;) ) :P

AttachDBFileName : عنوان ملف قاعدة البيانات المحلي .

Connect TimeOut : عدد الثواني التي يجب على الاتصال أن يغير حالته من مغلق إلى نشط دون مرورها .

Data Source : قمنا بذكر عملها وللإعادة ( اسم الخادم المراد الاتصال به ) .

Encrypt : تحديد بقيمة منطقية ( True, False ) أو بدائل شبيهة ( Yes, No ) ما إذا كنت تريد تشفير البيانات المرسلة بين الخادم والعميل أو لا .

Initial Catalogy أو DataBase : قمنا بذكره وللإعادة ( اسم قاعدة بيانات موجودة على نطاق الخادم ) .

Integrated Security : أيضاً قمنا بذكرها ( تحديد بقيمة منطقية اي ( True, False ) أو بدائل شبيهة ( Yes, No ) أو اختصار نوع الحماية ( SSPI ) لإخبار الاتصال عن حالة الحماية و التوثيق .

Network Library : من الاسم ( شبكة ) إذا كان للاتصال طرف يعمل عليه بنوع من أنواع اتصالات الشبكات المعترف عليها :

dbnmpntw

dbmsrpcn

dbmsadsn

dbmsgnet

dbmslpcn

dbmsspxn

dbmssocn

سيتم شرحهم لاحقاً ;) لاتشغل بالك بهم، ركز الأن

Packet Size : حجم بالـ( Byte ) للحزم التي سيقوم الـ( SQL ) بالتقيد بها بمعالجة البيانات في نطاق الشبكة، يجب أن تكون القيمة من مضاعفات الـ( 512 ) .

Password أو PWD : كلمة السر الخاصة بقاعدة البيانات .

User ID أو UID : معرف المستخدم ( اسم المستخدم ) الخاص بقاعدة البيانات .

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

المشروع التالي يجب أن يطبق على ( Console Application ) :

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.VisualBasic.Strings
Module Module1

Sub Main()
' تغيير الألوان للتوضيح
Console.BackgroundColor = ConsoleColor.White
Console.ForegroundColor = ConsoleColor.Blue
Console.Clear()
' تصريح اتصال سكيول جديد
Dim _SqlConnection As New SqlConnection()
' _ استخدام جملة المحاولة لملاحقة أو الاستفسار
' _ عن الأخطاء وتخطي عدم استجابة التطبيق
' في حال ورود خطأ ما
Try
With _SqlConnection
Console.WriteLine("Trying to create and open a new connection, Please wait...")
PrintSP()
.ConnectionString = "Server = .\sqlexpress; Integrated Security = True"
' اتصال
.Open()
Console.WriteLine("Connection opened!")
PrintSP()
' عرض البيانات التي تكلمنا عنها سابقاً
Console.WriteLine("Connection String ( {0} )", .ConnectionString)
Console.WriteLine("DataSource ( {0} )", .DataSource)
Console.WriteLine("Database ( {0} )", .Database)
Console.WriteLine("Server Version ( {0} )", .ServerVersion)
Console.WriteLine("Connection State ( {0} )", .State.ToString)
Console.WriteLine("Workstation Id ( {0} )", .WorkstationId)
End With
Catch Ex As Exception
' عرض الخطأ في حال حدوثه
Console.WriteLine("Error ( {0} )", Ex.ToString)
Finally
' إغلاق الاتصال في النهاية
_SqlConnection.Close()
PrintSP()
Console.WriteLine("Connection closed.")
PrintSP()
End Try
Console.WriteLine("Press any key to exit ...")
Console.ReadLine()
End Sub

Private Sub PrintSP()
Dim SP As String = "=-=-=-=-=-=-=-=-=-=-=-=-=-"
SP = (SP & SP & SP)
Console.WriteLine()
Console.WriteLine(SP)
Console.WriteLine()
End Sub

End Module

النتائج المتوقع الحصول عليها بشكل مشابه لبعض المعلومات :

post-178281-1255279950_thumb.jpg

لم يحدث أي خطأ، أليس كذلك ؟

مالأخطاء المتوقع حدوثها عند إجراء اتصال بمزود ما ؟

لايمكنني الجزم بشكل عام لكني كما ذكرنا ( المشاكل الشائعة ) :

1 - كتابة عبارة ما بشكل خاطئ في معلومات الاتصال : على سبيل المثال ( Srver ) عوضاً عن ( Server ) أو اي خطأ مطبعي غير مقصود :S .

2 - الخادم غير موجود أو لايعمل .

3 - قاعدة البيانات المشار إليها غير موجودة على نطاق الخادم .

4 - عنوان قاعدة البيانات المشار إليها غير موجودة .

5 - ملف قاعدة البيانات تالف .

6 - اسم المستخدم أو كلمة المرور غير صحيحـ(ـة) .

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

وهذا أيضاً ليس بالشيء الصعب :) ( من يصنع شيئاً يعرف ماطبيعة عمله وحاجانه ;) )

نأتي الأن لنجرب السابق على نوع أخر من المزودات لكننا سنستخدم نفس المحرك أي الـ( SQL Server ) :

Imports System
Imports System.Data
Imports System.Data.OleDb
Imports Microsoft.VisualBasic.Strings
Module Module1

Sub Main()
' تغيير الألوان للتوضيح
Console.BackgroundColor = ConsoleColor.White
Console.ForegroundColor = ConsoleColor.Blue
Console.Clear()
' تصريح اتصال سكيول جديد
Dim _OleDbConnection As New OleDbConnection()
' _ استخدام جملة المحاولة لملاحقة أو الاستفسار
' _ عن الأخطاء وتخطي عدم استجابة التطبيق
' في حال ورود خطأ ما
Try
With _OleDbConnection
Console.WriteLine("Trying to create and open a new connection, Please wait...")
PrintSP()
.ConnectionString = "Provider = SqlOleDb; Data Source = .\sqlexpress;" & _
"Integrated Security = SSPI"
' اتصال
.Open()
Console.WriteLine("Connection opened!")
PrintSP()
' عرض البيانات التي تكلمنا عنها سابقاً
Console.WriteLine("Connection String ( {0} )", .ConnectionString)
Console.WriteLine("DataSource ( {0} )", .DataSource)
Console.WriteLine("Database ( {0} )", .Database)
Console.WriteLine("Server Version ( {0} )", .ServerVersion)
Console.WriteLine("Connection State ( {0} )", .State.ToString)
Console.WriteLine("Provider ( {0} )", .Provider)
End With
Catch Ex As Exception
' عرض الخطأ في حال حدوثه
Console.WriteLine("Error ( {0} )", Ex.ToString)
Finally
' إغلاق الاتصال في النهاية
_OleDbConnection.Close()
PrintSP()
Console.WriteLine("Connection closed.")
PrintSP()
End Try
Console.WriteLine("Press any key to exit ...")
Console.ReadLine()
End Sub

Private Sub PrintSP()
Dim SP As String = "=-=-=-=-=-=-=-=-=-=-=-=-=-"
SP = (SP & SP & SP)
Console.WriteLine()
Console.WriteLine(SP)
Console.WriteLine()
End Sub

End Module

النتائج المتوقع الحصول عليها بشكل مشابه لبعض المعلومات :

post-178281-1255279958_thumb.jpg

كوظيفة :P للذين ييحبون التجربة لأنها في نظري الأهم بالنسبة للخبرة :)

اكتب ( Code ) شبيه بالسابق لكن يجب أن يكون اعتمادك على مزود و قاعد بيانات الـ( Access ) .

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

بالتوفيق .

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الأوامر أو بمعنى أخر الإجراءات والعمليات ( Commands )

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

وكما في كل مقال ( نتذكر ) أن ( Microsoft ) تدعم المزودات التالية ( Odbc, OleDb, Oracle, SQL Server, SQL Server CE ) وبالتالي كل منها له كائنات ( عناصر ) تقوم بمعالجة قواعد البيانات التابعة له عدا عن الـ( OleDb ) والـ( Odbc ) وذلك لأن كلهما قادر على اتصال بإحدى المزودات الأخرى عبر تطبيق ( إعداد ) طبقات الاتصال بالمحرك المستهدف .

لذلك وبهذا الدرس سنبدأ بالتشديد على استيراد المراجع ( References ) التي نحتاجها لاستخدام المزود المستهدف، في المقال السابق ( الاتصالات ) تم ذكر أسماء الفضاء لكل من المزودات وبذلك قبل أن نبدأ بكتابة ( Code ) لإنشاء اتصال وأوامر وما إلى ذلك علينا أن نستدعي المرجع، المراجع المطلوبة، وعلى سبيل المثال رأينا في أغلبية أمثلتنا السابقة أن الأكثر استخداماً هو الـ( SqlClient ) اي المزود التابع للـ(

) :

' ( 1 )
Imports System

' ( 2 )
Imports System.Data

' ( 3 )
Imports System.Data.SqlClient

( 1 ) : لست بحاجة لاستدعاء هذا المرجع لأنه من المراجع المفروضة .

( 2 ) : مصدر محركات جميع البيانات، أيضاً لست بحاجة لاستدعائه إلا في حال كنت تريد اختصار كتابة ( Imports System.Data.SqlClient ) واستعاضة بتصريح العناصر الخاصة بالـ( SqlClient ) على الشكل التالي : ( SqlClient.SqlCommand )، أو في حال أردت أن تستخدم كائنات من المرجع ( Data ) بشكل مباشر أي بدون ذكر اسم الفضاء ( Data ) .

( 3 ) : استدعاء المرجع ( SqlClient ) ليتم تصريح كائنات الـ( SqlClient ) بشكل مباشر وبدون ذكر اسم الفضاء وأيضاً بالنسبة للمرقمات كأنوع الـ( Sql ) .

نأتي الأن لكيفية إنشاء أمر جديد :

تصريح :

Imports System.Data.SqlClient

Public Class Form1

Private Sub CreateCommand()
Dim _SqlCommand As New SqlCommand("CommandText" )
MsgBox("SqlCommand has been created ." )
End Sub

End Class

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

Imports System.Data.SqlClient

Public Class Form1

Private Sub CreateCommand()
Dim _SqlCommand As New SqlCommand()
_SqlCommand.CommandText = "CommandText"
MsgBox("SqlCommand has been created ." )
End Sub

End Class

وطريقة أخرى العملية ( CreateCommand ) من كائن الاتصال والتي يمكن اتمامها بوجود اتصال مصرح، مثال :

Imports System.Data.SqlClient

Public Class Form1

Private Sub CreateCommand()
Dim _SqlConnection As New SqlConnection("ConnectionString" )
Dim _SqlCommand As SqlCommand = _SqlConnection.CreateCommand()
_SqlCommand.CommandText = "CommandText"
MsgBox("SqlCommand has been created ." )
End Sub

End Class

وبهذا نرى أن لتصريح امر جديد طريقتان ( تصريح بشكل مباشر عن طريق الكلمة ( New ) أو عن طريق استدعاء العملية ( CreateCommand ) من كائن اتصال مصرح ) .

الأن لنرى أهم العمليات التي يمكن استخدامها :

ExecutreNonQuery : أغلبية الاستخدام تتم عند التعامل مع إحدى العمليات الأساسية كالـ( Insert, Update, Delete ) أو عند استخدام أوامر إنشاء وحذف جدول ( Create Table, Drop Table )، عند قراءة عائدات هذه العملية فإنها تعيد عدد السجلات التي تم معالجتها خلال إحدى العمليات المذكورة لمعالجة السجلات ( Insert, Update, Delete ) .

ExecuteScalar : عند استخدام نظرية من نظريات الجمع مثلاً لتحصيل قيمة كـ( الأكبر [Maximumل]، الأصغر [Minimum]، المتوسط [Average] )، مهمة هذه العملية العملية إعادة قيمة وحيدة على هيئة كائن أي ( Object ) والتي يتم تميز نوعها الموروث من قبل الـ( VB ) .

ExecuteReader : لقراءة محصلة الاستعلام عبر الـ( Reader ) تكلمنا عنه سابقاً واستخدامه شبيه بالـ( Stream ) .

ExecuteXmlReader : قراءة محصلة الاستعلام على شكل ( XML ) .

post-178281-1256495666_thumb.jpg

لنأخذ شيء عملي يبسط فكرة استخدام العمليات السابقة :

لدينا الجدول التالي :

PK[iD Int Not Null], [FullName Nvarchar(45) Null]

--[-------7-------], [------Bashar Rabatt-------]

--[-------8-------], [-------Yamen Sameer-------]

--[-------9-------], [--------Ila Angel---------]

المقصود بالـ( PK ) هو ( Primary Key ) أي ( مفتاح أساسي ) تكلمنا عنه سابقاً :)، بعد إنتهائنا من دراسة أهم عناصر قواعد البيانات سوف نبدأ بإنشاء الجداول والتعرف على أنواع العلاقات وكيفية الربط بين الجدوال وسنرى أن أحد أهم عناصر العلاقات هو الـ( Primary Key ) .

Imports System.Data.Sqlclient
Module Module1
Private _ConnectionString As String = "Server=.\sqlexpress; " & _
"AttachDbFileName=C:\Test.mdf; Integrated Security = True; User Instance=True"
Sub Main()
' تغيير الألوان للتوضيح
Console.BackgroundColor = ConsoleColor.White
Console.ForegroundColor = ConsoleColor.Blue
Console.Clear()

Dim _Commands As String() = New String() _
{"Select Count(*) From Employees", _
"Insert Into Employees (FullName) Values ('Bill Gates')", _
"Delete From Employees Where FullName = 'Bill Gates'", _
"Select * From Employees"}
Dim _SqlConnection As SqlConnection
Dim _SqlCommand As SqlCommand
Try
Console.WriteLine("Creating a new connection .")
_SqlConnection = New SqlConnection(_ConnectionString)
Console.WriteLine("Trying to open a connection with '{0}' .", _SqlConnection.DataSource)
Console.WriteLine()
_SqlConnection.Open()
Console.WriteLine("Create a new command .")
Console.WriteLine()
_SqlCommand = _SqlConnection.CreateCommand
Console.WriteLine("Preparing to read an aggregated result")
_SqlCommand.CommandText = _Commands(0)
Console.WriteLine("Executing Command ( {0} )", _SqlCommand.CommandText)
Console.WriteLine("Row(s) Count {0}", _SqlCommand.ExecuteScalar.ToString)
Console.WriteLine("".PadRight(79, "="))
Console.WriteLine("Preparing to insert a new record .")
_SqlCommand.CommandText = _Commands(1)
Console.WriteLine("Executing Command ( {0} )", _SqlCommand.CommandText)
Console.WriteLine("Number Of Affected Rows {0}", _SqlCommand.ExecuteNonQuery)
Console.WriteLine()
Console.WriteLine("Preparing to read an aggregated result")
_SqlCommand.CommandText = _Commands(0)
Console.WriteLine("Executing Command ( {0} )", _SqlCommand.CommandText)
Console.WriteLine("Row(s) Count {0}", _SqlCommand.ExecuteScalar.ToString)
Console.WriteLine()
ReadInformation(_SqlCommand, _Commands(3))
Console.WriteLine("Preparing to delete the information of 'Bill Gates' .")
_SqlCommand.CommandText = _Commands(2)
Console.WriteLine("Executing Command ( {0} )", _SqlCommand.CommandText)
Console.WriteLine("Number Of Affected Rows {0}", _SqlCommand.ExecuteNonQuery)
Console.WriteLine()
Console.WriteLine("Preparing to read an aggregated result")
_SqlCommand.CommandText = _Commands(0)
Console.WriteLine("Executing Command ( {0} )", _SqlCommand.CommandText)
Console.WriteLine("Row(s) Count {0}", _SqlCommand.ExecuteScalar.ToString)
Console.WriteLine()
ReadInformation(_SqlCommand, _Commands(3))
Console.WriteLine()
Console.WriteLine("Done!")
Catch ex As Exception
Console.WriteLine("Error {0}", ex.ToString)
End Try
Console.WriteLine("Press any key to exit ...")
Console.ReadLine()
End Sub


Private Sub ReadInformation(ByVal CMD As SqlCommand, ByVal CMDTXT As String)
Console.WriteLine("Preparing to read table information .")
CMD.CommandText = CMDTXT
Console.WriteLine("Executing Command ( {0} )", CMD.CommandText)
Console.WriteLine()
Console.WriteLine("ID".PadRight(4) & " " & "Full Name")
Console.WriteLine("".PadRight(4, "=") & " " & "".PadRight(9, "="))
Dim Reader As SqlDataReader = CMD.ExecuteReader
Do While Reader.Read
Console.WriteLine(Reader.Item(0).ToString.PadRight(4) & " " & _
Reader.Item(1).ToString)
Loop
Reader.Close()
Console.WriteLine("".PadRight(79, "="))
End Sub
End Module

post-178281-1256495660_thumb.jpg

ذكرنا في وصف مقالنا هذا عن إنشاء أوامر بشكل بسيط وبشكل متقدم، مالمقصود بـ( شكل بسيط ) و ( شكل متقدم ) ؟

الشكل البسيط في إنشاء أوامر هو كتابة جميع محتويات استعلام وعملية بشكل نصي أي على سبيل المثال :

Dim CurrentID As Int32 = 5
Dim _SqlCommand As New SqlCommand("Select * From Table1 Where ID = " & CurrentID.ToString())

أو

Dim Value1 As String = "Ahmad", Value2 As String = "Arabi Katbi"
Dim _SqlCommand As New SqlCommand("Insert Into Friends (FirstName, LastName) Values " & _
"('" & Value1 & "', '" & Value2 & "')"

طريقة سهلة، اليس كذلك ؟

لكن هل هي الأفضل ؟ هل تقدم لك جميع ماتحتاج من أمان و تطور ؟

لنرى الشكل المتقدم ومن ثم قرر بنفسك مالأفضل ؟ ;)

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

مثال :

Dim _SqlCommand As New SqlCommand("Select FullName From People Where ID = @ID")
Dim _IDSqlParameter As New SqlParameter("@ID", SqlTypes.Int, 4, "ID")
_IDSqlParameter.Value = 1
_SqlCommand.Parameters.Add(_IDSqlParameter)
_SqlCommand.Prepare()

أو

Dim _SqlCommand As New SqlCommand("Insert Into People (FirstName, LastName, PhoneNumber)" & _
" Values (@FirstName, @LastName, @PhoneNumber)"
Dim _FirstNameSqlParam As New SqlParameter("@FirstName", SqlTypes.NVarchar, 15)
Dim _LastNameSqlParam As New SqlParameter("@LastName", SqlTypes.NVarchar, 25)
Dim _PhoneNumberSqlParam As New SqlParameter("@PhoneNumber", SqlTypes.Char, 15)

With _SqlCommand.Parameters
.Add( _FirstNameSqlParam ).Value = "Bashar"
.Add( _LastNameSqlParam ).Value = "Rabatt"
.Add( _PhoneNumberSqlParam ).Value = "+96311********"
End With

_SqlCommand.Prepare()

نرى الأن فائدة المعاملات اي الـ( Parameters ) والتي يمكن اختصارها بـ( Params )، أهم الخصائص التي يمكن إعدادها بالنسبة لعملنا الحالي هي :

اسم المعامل : كما في المثال السابق ( FirstName, @LastName, @PhoneNumber@ )

نوع المعامل : مالنوع المستخدم في تمثيل قيمة خلايا هذا الحقل ؟، كما في المثال ( SqlTypes.NVarchar, SqlTypes.NVarchar, SqlTypes.Char )

طول قيمة الخلية الأعظم : حسب النوع ولكن بالنسبة للنصوص فيتم تحديد طول قيمة الخلية التي تتبع نوع الـ( Char )، كما في المثال السابق ( 15, 25, 15 )

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

_SqlCommand.Parameters.Add( _FirstNameSqlParam ).Value

_SqlCommand.Parameters.Add( _LastNameSqlParam ).Value

_SqlCommand.Parameters.Add( _PhoneNumberSqlParam ).Value

للمعاملات اي الـ( Parameters ) استعمالات كثيرة وسنرى من خلال الدروس القادمة فائدة هذا الكائن من حيث المدخلات والمراجع وتنظيم عمليات القراءة والكتابة لجميع أنواع الـ( SQL Server ) أو أي نوع من أنواع المحركات الأخرى .

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

قارئ المعلومات ( Data Reader )

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

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

كائن الـ( DataReader ) بشكل عام أي بالنسبة لجميع المزودات هو كائن يحقق مبدأ الواجهة ( System.Data.IDataReader ) وكما ذكرنا في ماسبق أنه يمكن تشبيه الـ( DataReader ) بـ( Stream ) علماً أنه يملك الكثير من الخصائص المشابهة،

فهو قادر على قراءة البيانات أي ( نتائج الاستعلام ) بشكل متسلسل غير مؤقت يقرأ النتائج كل سجل على حده .

post-178281-1256750392_thumb.jpg

الموضوع بسيط جداً ولايحتاج إلى تركيز ولكنه يحتاج إلى تتبع بالنسبة لفقراته .

قبل أن نبدأ بعرض أمثلة وشرحها يجب أن تعلم أن الطريقة المثلة لإنشاء قارئ بيانات هي عن طريق استدعاء العملية ( ExecuteReader ) من عنصر الأمر أي الـ( Command ) المفروض ( المصرح ) .

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

Imports System.Data.SqlClient
Module MyConsoleApp
Private Const _ConnectionString As String = "Server=.\SqlExpress;" & _
"AttachDbFileName=C:\ABase.mdf; Integrated Security=True; User Instance=True"
Sub Main()
' تصريح اتصال
Dim _SqlConnection As SqlConnection
' تصريح أمر
Dim _SqlCommand As SqlCommand
' بدء جملة محاولة
Try
' تعريف وإعداد الاتصال
_SqlConnection = New SqlConnection(_ConnectionString)
' تعريف وإعداد الأمر
_SqlCommand = New SqlCommand("Select ID, FirstName, LastName, " & _
"SolidID From Transformations", _SqlConnection)
' فتح الاتصال
_SqlConnection.Open()
' تصريح وتنفيذ الاستدعاء لتحصيل قارئ بيانات
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader
' ( عنونة الحقول ( الأعمدة
Console.WriteLine("ID".PadRight(10, "-") & _
"FirstName".PadRight(15, "-") & "LastName".PadRight(25, "-") & _
"SolidID".PadRight(20, "-"))
Console.WriteLine()
' استخدام حلقة تكرارية ذات مبدأ 'بينما' لقراءة النتائج
' أي مازال هناك حقول للقراءة True مازالت Read بينما القيمة المعادة عبر العملية
Do While _SqlDataReader.Read
' قراءة وتنسيق نتائج الاستعلام
Console.WriteLine(_SqlDataReader.Item(0).ToString.PadRight(10, " ") & _
_SqlDataReader.Item(1).ToString.PadRight(15, " ") & _
_SqlDataReader.Item(2).ToString.PadRight(25, " ") & _
_SqlDataReader.Item(3).ToString.PadRight(20, " "))
Loop
Catch SqlEx As SqlException
Console.WriteLine(SqlEx.ToString)
Catch Ex As Exception
Console.WriteLine(Ex.ToString)
End Try
Console.ReadLine()
End Sub

End Module

العمليات التابعة للـ( DataReader ) هناك بعض العمليات التي تبدأ بالفعل ( Get ) أي ( اجلب ) ويليها اسم نوع معلوم .

ماالمقصود باسم نوع معلوم ؟ نعلم جميعاً أننا نملك عدة أنواع يمكننا استخدمها مع المتغيرات أو الثوابت في تطبيقاتنا ومنها الـ( Integer و Long و String ووووو... ) وكما ذكرنا سابقاً أن هناك الكثير من الأنواع المتقابلة في الـ( Visual Basic.Net ) والـ( Sql Server )

وبالنسبة لحديثنا عن الـ( DataReader ) في الـ( Visual Baisc.Net ) نجد أن أسماء الأنواع التي ستلي الكلمة ( Get ) ستكون إحدى أسماء الأنواع في الـ( VB.Nnet ) وعلى سبيل المثال أنه لدينا حقل اسمه ( ID ) ويدعم نوع ( Int ) والذي يقابل ( Int32 ) في الـ( VB.Net ) وعلى فرض ذلك نجد أنه علينا استدعاء العملية ( GetInt32 ) .

ماالذي تحتاجه هذه العمليات لتنفذ ؟ وبما تفيدني ؟

بالنسبة للسؤال الأول - عند استدعاء هذه العملية ستلاحظ أنها تطلب منك رقم الخلية أي القيمة التي تقابل الحقل كذا من السجل الحالي، وهذا كل ماتحتاجه .

بالنسبة للسؤال الثاني - الكثير من المبرمجين يفضلون تحديد الأنواع التي تتم المعالجة عبرها وذلك لإتمام العمل بكافئة وأمان أكبر ومهمة كل من عمليات الجلب هي إعادة القيمة المضمنة بصيغة النوع المحدد وكما في مثالنا السابق ( Int ) أي ستعيد قيمة من نوع ( Integer ) والذي يحل محل الـ( Int32 ) أيضاً .

عمليات الجلب لأنواع الـ( SQL ) :

GetBoolean : كـ( bit )

GetByte : كـ( tinyint )

GetBytes : كـ( binary, image, varbinary, timestamp )

GetChars : كـ( char, nchar, ntext, nvarchar, varchar )

GetDateTime : كـ( datetime, smalldatetime)

GetDecimal : كـ( decimal, money, numeric, smallmoney )

GetDouble : كـ( float )

GetFloat : كـ( real )

GetGuid : كـ( uniqueidentifier )

GetInt16 : كـ( smallint )

GetInt32 : كـ( int )

GetInt64 : كـ( bigint )

GetString : كـ( char, nchar, ntext, nvarchar, varchar )

GetValue : كـ( sql_variant )

عمليات الجلب لأنواع الـ( OLE DB ) :

GetBoolean : كـ( DBType_Bool )

GetByte : كـ( DBType_I1 )

GetBytes : كـ( DBType_Bytes )

GetDateTime : كـ( DBType_Date, DBType_DBDate, DBType_DBTime, DBType_DBTimeStamp)

GetDecimal : كـ( DBType_CV, DBType_Decimal, DBType_Numeric )

GetDouble : كـ( DBType_R8 )

GetFloat : كـ( DBType_R4 )

GetGuid : كـ( DBType_GUID )

GetInt16 : كـ( DBType_I2 )

GetInt32 : كـ( DBType_I4 )

GetInt64 : كـ( DBType_I8 )

GetString : كـ( DBType_BSTR, DBType_STR, DBType_LongVarChar, DBType_WVarChar, DBType_WChar )

GetValue : كـ( DBType_UI2, DBType_UI4, DBType_UI8, DBType_Variant )

بالنسبة لـ:

DBType_UI2 تمثل UIn16 أو UShort بالـ( Visual Basic.Net )

DBType_UI4 تمثل UInt32 أو UInteger بالـ( Visual Basic.Net )

DBType_UI8 تمثل UInt64 أو ULong بالـ( Visual Basic.Net )

مثال عن ماسبق :

Imports System.Data.SqlClient
Module MyConsoleApp
Private Const _ConnectionString As String = "Server=.\SqlExpress;" & _
"AttachDbFileName=C:\ABase.mdf; Integrated Security=True; User Instance=True"
Sub Main()
' تصريح اتصال
Dim _SqlConnection As SqlConnection
' تصريح أمر
Dim _SqlCommand As SqlCommand
' بدء جملة محاولة
Try
' تعريف وإعداد الاتصال
_SqlConnection = New SqlConnection(_ConnectionString)
' تعريف وإعداد الأمر
_SqlCommand = New SqlCommand("Select ID, FirstName From Transformations", _
_SqlConnection)
' فتح الاتصال
_SqlConnection.Open()
' تصريح وتنفيذ الاستدعاء لتحصيل قارئ بيانات
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader
' جعل القارئ يقوم بقراءة السجل الأول
_SqlDataReader.Read()
' تصريح متغيرات وإعداد قيمها عن طريق عمليات الجلب
Dim ID As Object = _SqlDataReader.GetInt32(0)
Dim FirstName As Object = _SqlDataReader.GetString(1)
' كتابة كل من القيم المستوردة والأنواع التابعة لها
Console.WriteLine(ID.ToString.PadRight(20, " ") & " = " & ID.GetType.Name)
Console.WriteLine(FirstName.ToString.PadRight(20, " ") & " = " & FirstName.GetType.Name)
Catch SqlEx As SqlException
Console.WriteLine(SqlEx.ToString)
Catch Ex As Exception
Console.WriteLine(Ex.ToString)
End Try
Console.ReadLine()
End Sub

End Module

نأتي الأن لخصائص والعمليات الخاصة بمعلومات الأساس وهي :

Depth : تعيد قيمة تحدد عمق تداخل السجلات .

Fieldcount : تعيد قيمة تمثل عدد الحقول ( عدد خلايا السجل ) .

GetDataTypeName : عملية تطلب رقم الحقل وتعيد قيمة نصية تمثل نوع الحقل .

GetFieldType : عملية تطلب رقم الحقل وتعيد النوع المقابل في ( VB.Net ) .

GetName : عملية تطلب رقم الحقل وتعيد قيمة نصية تمثل اسم الحقل .

GetOrdinal : عملية تطلب قيمة نصية تمثل اسم الحقل وتعيد ترتيبه بين الأعمدة الأخرى .

GetSchemaTable : عملية تعيد المعلومات تكوين الجدول .

HasRows : خاصية تعيد قيمة منطقية يحدد بها ماإذا كان الكائن ( DataReader ) يحوي سجلات أم لا .

RecordsAffected : عدد السجلات المعدلة، المدخلة أو المحذوفة .

مثال عن استدعاء بعض العمليات والخصائص :

Imports System.Data.SqlClient
Module MyConsoleApp
Private Const _ConnectionString As String = "Server=.\SqlExpress;" & _
"AttachDbFileName=C:\ABase.mdf; Integrated Security=True; User Instance=True"
Sub Main()
' تصريح اتصال
Dim _SqlConnection As SqlConnection
' تصريح أمر
Dim _SqlCommand As SqlCommand
' بدء جملة محاولة
Try
' تعريف وإعداد الاتصال
_SqlConnection = New SqlConnection(_ConnectionString)
' تعريف وإعداد الأمر
_SqlCommand = New SqlCommand("Select * From Transformations", _
_SqlConnection)
' فتح الاتصال
_SqlConnection.Open()
' تصريح وتنفيذ الاستدعاء لتحصيل قارئ بيانات
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader
Console.WriteLine("This Table Has {0} Column(s)", _SqlDataReader.FieldCount.ToString)
Console.WriteLine()
WriteSP() : WriteSP()
For I As Int32 = 0 To _SqlDataReader.FieldCount - 1
Console.WriteLine("Column Index = {0}", I.ToString)
Console.WriteLine(" Name = {0}", _
_SqlDataReader.GetName(I))
Console.WriteLine(" Type Name = {0}", _
_SqlDataReader.GetDataTypeName(I))
Console.WriteLine(" .NET Type Name = {0}", _
_SqlDataReader.GetFieldType(I).Name)
WriteSP()
Next
WriteSP()
Catch SqlEx As SqlException
Console.WriteLine(SqlEx.ToString)
Catch Ex As Exception
Console.WriteLine(Ex.ToString)
End Try
Console.ReadLine()
End Sub

Private Sub WriteSP()
Console.WriteLine("".PadLeft(30, "="))
End Sub

End Module

post-178281-1256750407_thumb.jpg

حسناً قبل أن نرى كيف يمكننا معالجة عدة نتائج بآن واحد، لنرى كيف يمكننا تحصيل معلومات جدول كامل ;) :

Imports System.Data.SqlClient
Module MyConsoleApp
Private Const _ConnectionString As String = "Server=.\SqlExpress;" & _
"AttachDbFileName=C:\ABase.mdf; Integrated Security=True; User Instance=True"
Sub Main()
' تصريح اتصال
Dim _SqlConnection As SqlConnection
' تصريح أمر
Dim _SqlCommand As SqlCommand
' بدء جملة محاولة
Try
' تعريف وإعداد الاتصال
_SqlConnection = New SqlConnection(_ConnectionString)
' تعريف وإعداد الأمر
_SqlCommand = New SqlCommand("Select * From Transformations", _
_SqlConnection)
' فتح الاتصال
_SqlConnection.Open()
' تصريح وتنفيذ الاستدعاء لتحصيل قارئ بيانات
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader
' تصريح جدول جديد لتخزين معلومات الجدول المستعلم عنه بشكل مؤقت
Dim Schema As DataTable = _SqlDataReader.GetSchemaTable
' استخدام حلقتان تكراريتان مصدريتان لقراءة معلومات الجدول
For Each Ro As DataRow In Schema.Rows
For Each Col As DataColumn In Schema.Columns
Console.WriteLine("Property Name = {0}; Value = {1}", _
Col.ColumnName, Ro(Col).ToString)
Next
WriteSP()
Next
Catch SqlEx As SqlException
Console.WriteLine(SqlEx.ToString)
Catch Ex As Exception
Console.WriteLine(Ex.ToString)
End Try
Console.ReadLine()
End Sub

Private Sub WriteSP()
Console.WriteLine("".PadLeft(30, "="))
End Sub

End Module

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

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

ستقول : أمر لكل استعلام وقارئ بيانات لكل نتيجة ؟ كلا !

ستقول : أمر واحد بتغير جملة الاستعلام وقارئ بيانات لجميع النتائج ؟ ( ممكن )

ستسأل : هل هناك من طريقة أفضل ؟ ( كلا ولكن يوجد طريقة تساعدك على اتمام الاقتراح الثاني بدون تعديل جملة الاستعلام )

ستسأل : كيف ؟ ( كما ذكرنا أنه من ممكن دمج الاسعلامات فيما بينها على التسلسل ويمكن عندها ترتيب الاستعلامات بحيث أن نتائج الاستعلام ستعرض على حسب فرزها على التسلسل )

لحظة !، ماذا تقصد بـ( ترتيب الاستعلامات بحيث أن نتائج الاستعلام ستعرض على حسب فرزها على التوالي أو على التسلسل ؟ )

حسناً لنفرض أن لدينا قاعدة بيانات تحوي خمسة جداول ( Table1, Table2, Table3, Table4, Table5 )ونريد تحصيل جميع بيانات الجداول بعنصر واحد لكننا نريد أيضاً قراءة بيانات كل جدول بشكل منفصل، في بادئ الأمر سيتوجب علينا كتابة استعلام لكل جدول :

Dim Sql1 As String = "Select * From Table1"
Dim Sql2 As String = "Select * From Table2"
Dim Sql3 As String = "Select * From Table3"
Dim Sql4 As String = "Select * From Table4"
Dim Sql5 As String = "Select * From Table5"

وكما ذكر فيما سبق أننا بحاجة إلى دمج الاستعلامات على التسلسل مع العلم أن ترتيب الاستعلامات هو أساس فرزها على التسلسل أي :

Dim Sql As String = Sql1 & " " & Sql2 & " " & Sql3 & " " & Sql5 & " " & Sql4

post-178281-1256750401_thumb.jpg

النتائج :

النتيجة رقم 1 = بيانات الجدول رقم ( 1 )

النتيجة رقم 2 = بيانات الجدول رقم ( 2 )

النتيجة رقم 3 = بيانات الجدول رقم ( 3 )

النتيجة رقم 4 = بيانات الجدول رقم ( 5 )

النتيجة رقم 5 = بيانات الجدول رقم ( 4 )

حسناً ! وصلت الفكرة ! :P لكن كيف يمكنني قراءة هذه النتائج بواسطة العنصر ( DataReader ) ؟

وصلنا إلى المهم :)، من بين عمليات الكائن ( DataReader ) عملية تدعى ( NextResult ) هذه العملية تجعل الـ( DataAdapter ) يقفز من نتيجة استعلام إلى نتيجة الاستعلام التي تليها وبذلك نفهم أن علينا استخدام حلفتان تكراريتان يعتمدان اسلوب شرط تحقق قيمة منطقية خلال القراءة، الحلقة التكرارية الأولى تستخدم لقراءة جميع النتائج والحلقة التكرارية الثانية والمضمنة ضمن الحلقة التكرارية الأولى مهمتها قراءة بيانات نتائج الاستعلام الحالي .

لنرى مثال عنما ذكر :

Imports System.Data.SqlClient
Module MyConsoleApp
Private Const _ConnectionString As String = "Server=.\SqlExpress;" & _
"AttachDbFileName=C:\ABase.mdf; Integrated Security=True; User Instance=True"
Sub Main()
' تصريح اتصال
Dim _SqlConnection As SqlConnection
' تصريح أمر
Dim _SqlCommand As SqlCommand
' تصريح جمل الاستعلام
Dim Sql1 As String = "Select * From Systems"
Dim Sql2 As String = "Select * From Devices"
Dim Sql3 As String = "Select * From Transformations"
' دمج جمل الاستعلام
Dim Sql As String = Sql1 & " " & Sql2 & " " & Sql3
' بدء جملة محاولة
Try
' تعريف وإعداد الاتصال
_SqlConnection = New SqlConnection(_ConnectionString)
' تعريف وإعداد الأمر
_SqlCommand = New SqlCommand(Sql, _
_SqlConnection)
' فتح الاتصال
_SqlConnection.Open()
' تصريح وتنفيذ الاستدعاء لتحصيل قارئ بيانات
Dim _SqlDataReader As SqlDataReader = _SqlCommand.ExecuteReader
' تصريح جدول جديد لتخزين معلومات الجدول المستعلم عنه بشكل مؤقت
Do
Do While _SqlDataReader.Read
For I As Int32 = 0 To _SqlDataReader.FieldCount - 1
Console.Write(_SqlDataReader(I).ToString.PadRight("18"))
Next
Console.WriteLine()
Loop
WriteSP()
' لاحظ العبارة التالية، قم بالدوران بينما هناك نتائج استعلام أخرى
' العملية تعيد قيمة منطقية التي يحدد فيها إن كان هناك نتائج أخرى
Loop While _SqlDataReader.NextResult
Catch SqlEx As SqlException
Console.WriteLine(SqlEx.ToString)
Catch Ex As Exception
Console.WriteLine(Ex.ToString)
End Try
Console.ReadLine()
End Sub

Private Sub WriteSP()
Console.WriteLine("".PadLeft(79, "="))
End Sub

End Module

post-178281-1256750380_thumb.jpg

انتهينا !، الدرس المقبل سيكون متقدم أكثر وسنتحدث فيه عن الـ( DataAdapter ) و الـ( DataSet ) .

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بنك المعلومات وجسر المعلومات ( DataSet and DataAdapter )

كما رأينا في الدرس السابق أن لقراءة مجموعة معلومات من قاعدة بيانات علينا استخدام مايدعى بالـ( DataReader ) وذكرنا أيضاً أن من إحدى خصائصه القراءة بشكل متسلسل وأيضاً معالجة عدة استعلامات بعنصرين أساسيين وهما الـ( Command ) أي الأمر والـ( DataReader ) أي قارئ المعلومات وبيينا أن لقراءة مجموعة معلومات تم جمعها بشكل منفصل ( بدمج عدة استعلامات مع بعضها البعض ) يتم عن طريق استدعاء العملية ( NextResult ) وكما نرى الأن من خلال هذا الوصف أن العامل الأساسي في قراءة المعلومات من قواعد البيانات بشكل مباشر ( أي هناك اتصال بين محرك قواعد البيانات والقاعدة المستهدفة ) هو الـ( DataReader ) .

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

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

1 - أن يذهب كل مندوب إلى بعض المراكز المعتمدة ليأتي بالوصول كل حين وأخر .

2 - أن يذهب كل مندوب إلى بعض المراكز المعتمدة ليأتي بالوصول حسب رغبة مدير المركز المعتمد .

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

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

تعالوا نحللها بشكل برمجي وباستخدم ( Dataset )

قاعدة البيانات - الشركة

المندوب - الاتصال

المركز المعتمد - التطبيق الذي يستخدم الـ( Dataset )

الوصول المقطوعة مع الزبائن - البيانات التي سيتم إضافتها

الوصول المعادة من الشركة إلى المراكز المعتمد - نتائج البيانات بعض الإضافة

النتائج تمثل عدد مرات تدقيق المراكز خلال زمن قدره اسبوع واحد.

الحل 1 :

Dim TripsCount As Int32 = 0
Do While YouStillAlive
Create Connection
Read Data Into Dataset
Close Connection
Edit Data From Dataset
CreateConnection
Update Data From Dataset To Database
AnyErrors ?
Try Correct Them
Close Connection
Create Connection
Copy Data From Database To A New Dataset
Read Dataset
Select * From Forums Where Forum.ID = ForumID
Close Connection
TripsCount += 1
Loop

Console.WriteLine("Trips Count " & TripsCount.ToString)

Result
900

الحل 2 :

Dim TripsCount As Int32 = 0
Do While YouStillAlive
If AManagerCallYou Then
Create Connection
Read Data Into Dataset
Close Connection
Edit Data From Dataset
CreateConnection
Update Data From Dataset To Database
AnyErrors ?
Try Correct Them
Close Connection
Create Connection
Copy Data From Database To A New Dataset
Read Dataset
Select * From Forums Where Forum.ID = ForumID
Close Connection
TripsCount += 1
End If
Loop
Console.WriteLine("Trips Count " & TripsCount.ToString)

Result
700

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

الحل 3 :

Dim TripsCount As Int32 = 0
ٍSub DailyTimer_Tick()
Create Connection
Read Data Into Dataset
Close Connection
Edit Data From Dataset
CreateConnection
Update Data From Dataset To Database
AnyErrors ?
Try Correct Them
Close Connection
Create Connection
Copy Data From Database To A New Dataset
Read Dataset
Select * From Forums Where Forum.ID = ForumID
Close Connection
TripsCount += 1
End Sub

Console.WriteLine("Trips Count " & TripsCount.ToString)

Result
210

الحل رقم 4 :

Dim TripsCount As Int32 = 0
ٍSub WeeklyTimer_Tick()
Create Connection
Read Data Into Dataset
Close Connection
Edit Data From Dataset
CreateConnection
Update Data From Dataset To Database
AnyErrors ?
Try Correct Them
Close Connection
Create Connection
Copy Data From Database To A New Dataset
Read Dataset
Select * From Forums Where Forum.ID = ForumID
Close Connection
TripsCount += 1
End Sub

Console.WriteLine("Trips Count " & TripsCount.ToString)

Result
30

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

كما ذكرنا في الطلب الأول أنه عليك تكوين نظام لجمع الوصول بالشكل الأفضل والأسرع :

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

الفائدة مساعدة المندوبين في تخفيف عدد مرات التدقيق الأسبوعية وذلك بسبب تقبلهم الوظيفية بالراتب التي تقدمه الشركة، هل كنت لتقبل بالحل الأول براتب يعد متوسط ؟ ---> ( كلا !!! ) .

على فرض أن راتب ثابت ومقداره :

21000

الراتب الاسبوعي ( 5250 )

عدد مرات التدقيق بالحل الرابع = ( 30 / 10 ) = 3

5000 / 3 = 1750 أي ثمن التدقيق الواحد ( 1750 ) ( رحلة المندوب :P )

الراتب الاسبوعي المتوجب دفعه بالنسبة للحل الثالث والذي يفرض على كل مندوب التدقيق ( 210 / 10 ) = 21 مرة اسبوعياً:

1750 * 21 = 36750 يحق للمندوب زيادة بنسبة ( 75% ) على الراتب الثابت

الراتب الاسبوعي المتوجب دفعه بالنسبة للحل الثاني والذي يفرض على كل مندوب التدقيق ( 700 / 10 ) = 70 مرة اسبوعياً :

1750 * 70 = 122500 يحق للمندوب زيادة بنسبة ( 483.333% تقريباً ) على الراتب الثابت

الراتب الاسبوعي المتوجب دفعه بالنسبة للحل الأول والذي يفرض على كل مندوب التدقيق ( 900 / 10 ) = 90 مرة اسبوعياً :

1750 * 90 = 157500 يحق للمندوب زيادة بنسبة ( 650% ) على الراتب الثابت

تخيل يرعاك الله !! :)

الموضوع لا يتمحور على مناقشة أمور حسابية وإنما الأمور التي تتعلق بالسرعة والآداء والتوفير ( بالنسبة للبرمجة كلما قل عدد الـ( Bytes ) المستخدمة أصبح التطبيق أسرع ) ، المثال السابق يمثل صورة استخدام الـ( Dataset ) بالنسبة للحياة العملية، ولنوضح الصورة بشكل أفضل تعالوا نرى مثال عن الطرق الأكثر شيوعاً في تعديل بيانات قاعدة ما عبر الانترنت .

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

بدون استخدام الـ( Dataset ) أي بالإعتماد على الـ( DataReader ) في عملية القراءة والـ( Command ) في عملية الإضافة، التعديل أو الحذف وهكذا في كل أمر تنفذه :

post-178281-1257890896_thumb.jpg

نلاحظ خطوات العمل من المخطط السابق :

1 - إنشاء اتصال .

2 - فتح اتصال مع البيانات بين العميل والخادم .

3 - إنشاء أمر وإعداد جملة استعلام لجلب البيانات المطلوب، تمرير البيانات التي تم استيرادها إلى قارئ البيانات ليتم قرأتها داخل تطبيق العميل .

4 - إغلاق الاتصال والانتظار بينما يقوم العميل بإضافة، تعديل أو حذف سجل ما .

5 - إعادة فتح الاتصال .

6 - إنشاء أمر جديد وإعداد نص عملية ( الإضافة، التعديل أو الحذف ) ومن ثم تنفيذ العملية عبر ( ExecuteNonQuery ) .

7 - إغلاق الاتصال .

8 - التخلص من كائن الاتصال وماإلى ذلك .

لاحظ الخط الواصل بين أول خطوة وآخر خطوة، الخط يدل على أنه في كل مرة يريد العميل تعديل جزء بسيط من البيانات أي ( استخدام عملية ما ) سيتوجب على التطبيق العبور عبر خطوات العمل المذكورة وكما هو مبين بشكل وهمي بالنسبة للـ( Bytes ) المستخدمة فإن التكلفة ستكون أكبر والسرعة ستكون أبطىء، فماالحل ؟

فكر فكر فكر ...........

بنك المعلومات ( Dataset ) يخولك أن تقوم باستيراد جميع أو جزء من المعلومات ليقوم بتخزينها في الذاكرة بشكل مؤقت وأيضاً يخولك من إضافة أو تعديل أو حذف أي شيء بدون الحاجة للاتصال بقاعدة البيانات ولكن هذا لايعني أن قاعدة البيانات تعلم بالغيب ولكن المقصود وكما ذكرنا في السابق أن بنك المعلومات يأخذ صورة عامة عن العناصر المستهدفة من قاعدة بيانات ما، نفهم أن وظيفة هذا الكائن هو تحويل قاعدة البيانات بالشكل التابعة له إلى مجموعة من الصفوف ( Classes ) مورثة عن صفوف أخرى كالـ( DataTable, DataColumn, DataRow, Etc.. ) والعمليات ووو..الخ...

وبالنسبة لبنك المعلومات أي الـ( Dataset ) فيجب إرسال معلوماتها المحدثة إلى قاعدة البيانات دفعة واحدة عند حلول الوقت المناسب لذلك، دقق بالصورة التالية واتبع الأسهم لتفهم قكرة تحويل عناصر قاعدة بيانات إلى عناصر مقابلة في الـ( Visual Basic.Net ) وذلك لتسهيل عملية المعالجة ضمن بيئة الـ( .NET Framework ) :

post-178281-1257890916_thumb.jpg

الـ( Code ) السابق لايمثل الـ( Code ) الشامل للجدول المعروض في الصورة السابقة بل يمثل إحدى أهم عناصر الـ( Dataset ) ولنرى مخطط الكائن ( Dataset ) بشكل أوضح :

post-178281-1257890902_thumb.jpg

لاحظ -- يتألف الكائن ( Dataset ) من :

1 - مجموعة من الجداول، التي تتألف من ( (جدول يحوي مجموعة من الحقول ( حقل، حقل، حقل ) ومجموعة من السجلات ( سجل، سجل، سجل ))، (جدول يحوي مجموعة من الحقول ( حقل، حقل، حقل ) ومجموعة من السجلات ( سجل، سجل، سجل )) )

2 - مجموعة من العلاقات ( (علاقة (الجدلول المستهدف، ( المفتاح الأساسي، المفتاح المعتمد )))، (علاقة (الجدلول المستهدف، ( المفتاح الأساسي، المفتاح المعتمد ))) )

كمقارنة بين عناصر الـ( Visual Basic.Net ) وعناصر قواعد البيانات :

Database = Class Inherits (System.Data.DataSet)
Table = Class Inherits (System.Data.DataTable) and Implements (System.Collections.IEnumerable)
Row = Class Inherits (System.Data.DataRow)
Relation = Class Inherits (System.Data.DataRelation)
View = Class Inherits (System.Data.DataView)
Stored Procedure = Class Inherits (System.ComponentModel.Component)
Inline Function = Class Inherits (System.Data.DataTable) and Implements (System.Collections.IEnumerable)
Table-Valued Function = Class Inherits (System.Data.DataTable) and Implements (System.Collections.IEnumerable)
Scalar-Valued Function = Included In "InitCommandCollection" Sub As Command

حسناً كفاناً حديثاً عن هذا الكائن، لنرى مالذي يساعده في إكمال عملية القراءة والكتابة فكما عرفنا أن الجداول تُمثل على شكل صفوف مورثة عن الكائن ( DataTable ) ولكن ماالذي يملأ هذه الجداول وماالذي يحدث قاعدة البيانات ؟

يعد الـ( DataAdapter ) كجسر يتم فيه مقايضة البيانات في اتجاهين معاكسين وذلك لأن عملية الملء ( Fill ) تقوم باستيراد البيانات من قاعدة البيانات ومن ثم تقوم بتصريح (إدخال) البيانات في الصفوف الملائمة . أما بالنسبة للعملية ( Update ) فتقوم باستيراد البيانات من بنك المعلومات ( Dataset ) ومن ثم تقوم بتنفيذ الأوامر الملائمة ليتم تحديث القاعدة .

حالة الـ( DataAdapter ) في كلا العملتين :

post-178281-1257890890_thumb.jpg

وبالنسبة لاحتياجاته :

post-178281-1257890909_thumb.jpg

شكل تصاريحه :

Dim _SqlDataAdapter As System.Data.SqlDataAdapter = New SqlDataAdapter()
Dim _SqlDataAdapter As System.Data.SqlDataAdapter = New SqlDataAdapter(_SqlCommand)
Dim _SqlDataAdapter As SqlDataAdapter = New System.Data.SqlDataAdapter(_CommandText, _SqlConnection)
Dim _SqlDataAdapter As SqlDataAdapter = New System.Data.SqlDataAdapter(_CommandText, _ConnectionString)

أما بالنسبة لتصريح الـ( Dataset ) :

Dim _DataSet As New System.Data.DataSet()
Dim _DataSet As New System.Data.DataSet("DataSetName")

والأن وبعد أن فهمنا مخططات وخطوات عمل كل من الـ( Dataset ) والـ( DataAdapter ) لنبدأ مع مثال بسيط :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _QueryCommandText As String = "Select * From Products Where UnitPrice > 25"

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter(_QueryCommandText, _SqlConnection)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Products")

Dim _DataTable As DataTable = _DataSet.Tables("Products")

For Each DRow As DataRow In _DataTable.Rows
For Each DCol As DataColumn In _DataTable.Columns
Console.WriteLine(DRow(DCol))
Next DCol
Console.WriteLine()
Next DRow

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

شرح الـ( Code ) :

في بادئ الأمر قمنا باستيراد مايلزمنا من مراجع للاتصال بقاعدة بيانات تابعة للمزود ( Sql Server ) ولاستخدام عناصر هذا المرجع، ثم قمنا بتصريح متغير نصي والذي سميناه ( ConnectionString ) وذلك لأنه سيحوي نص معلومات الاتصال بقاعدة بيانات ( Sql ) وقمنا أيضاً بتصريح متغير أخر سميناه ( SelectCommandText ) أي نص أمر الاستعلام، بعد ذلك بدأنا بالمطلوب وهو :

أولاً - تصريح كائن ( DataAdapter ) وإعداد خصائصه الأساسية وهي ( CommandText و Connection ) .

ثانياً - تصريح كائن ( DataSet ) وحتى هذا السطر الـ( DataSet ) فارغة :P .

ثالثاً - استخدام عملية الملء والتي تحدثنا عنها سابقا ( والتي وظيفتها استيراد البيانات من القاعدة وإدخالها بالكائن ( Dataset ) أو يمكن الإستعاضة بـ( DataTable ) أيضاً، سنتكلم عن هذا لاحقاً ) .

رابعاً - بعد عملية الملء قمنا بتصريح ( DataTable ) لنختصر كتابة العبارة ( _DataSet.Tables("Products") ) في كل مرة نريد الاستعلام عم معلومة ما .

خامساً - استخدام حلقتان تكراريتان لقراءة معلومات جدول المنتجات وكتبة البيانات على نافذة الـ( Console Application ) .

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

وبنفس الطريقة التي قمنا باستخدامها مع الـ( DataReader ) لتحصيل بيانات عدة استعلامات في عملية واحدة، نقوم بدمج نصوص الاستعلامات لتصبح نصاً واحداً :

Dim _SqlDataAdapter As System.Data.SqlDataAdapter = New SqlDataAdapter()
Dim _SqlDataAdapter As System.Data.SqlDataAdapter = New SqlDataAdapter(_SqlCommand)
Dim _SqlDataAdapter As SqlDataAdapter = New System.Data.SqlDataAdapter(_CommandText, _SqlConnection)
Dim _SqlDataAdapter As SqlDataAdapter = New System.Data.SqlDataAdapter(_CommandText, _ConnectionString)

أما بالنسبة لتصريح الـ( Dataset ) :

Dim _DataSet As New System.Data.DataSet()
Dim _DataSet As New System.Data.DataSet("DataSetName")

والأن وبعد أن فهمنا مخططات وخطوات عمل كل من الـ( Dataset ) والـ( DataAdapter ) لنبدأ مع مثال بسيط :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _ProductsCommandText As String = "Select * From Products Where UnitPrice > 25"
Dim _EmployeesCommandText As String = "Select * From Employees Where FirstName Like " & _
"'" & "A%'"

Dim _QueryCommandText As String = _ProductsCommandText & " " _EmployeesCommandText

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter(_QueryCommandText, _SqlConnection)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Products")

Dim _ProductsDataTable As DataTable = _DataSet.Tables("Products")
Dim _EmployeesDataTable As DataTable = _DataSet.Tables("Employees")

Console.WriteLine("Products Table:")
For Each DRow As DataRow In _ProductsDataTable.Rows
For Each DCol As DataColumn In _ProductsDataTable.Columns
Console.WriteLine(DRow(DCol))
Next DCol
Console.WriteLine()
Next DRow

Console.WriteLine()

Console.WriteLine("Employees Table:")
For Each DRow As DataRow In _EmployeesDataTable.Rows
For Each DCol As DataColumn In _EmployeesDataTable.Columns
Console.WriteLine(DRow(DCol))
Next DCol
Console.WriteLine()
Next DRow

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

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

قبل أن نرى كيفية إضافة، تعديل أو حذف بعض البيانات علينا أن نعرف أن جميع العمليات الرئيسة المذكورة تتم عبر إستدعاء إجراء واحد وهو ( Update ) أي ( System.Data.SqlClinet.SqlAdapter.Update() )

إضافة بيانات جديدة إلى جدول ما باستخدام الـ( Dataset ) والـ( DataAdapter ) :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _QueryCommandText As String = "Select * From Employees"
Dim _InsertCommandText As String = "Insert Into Employees " & _
"(FirstName, LastName, TitleOfCourtesy, City, Country Values " & _
"(@FirstName, @LastName, @TitleOfCourtesy, @City, @Country)"

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter(_QueryCommandText, _SqlConnection)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Employees")

Dim _DataTable As DataTable = _DataSet.Tables("Employees")

Dim _EmployeeRow As DataRow = _DataTable.NewRow()
_EmployeeRow("FirstName") = "Bashar"
_EmployeeRow("LastName") = "Rabatt"
_EmployeeRow("TitleOfCourtesy") = "BasharVS"
_EmployeeRow("City") = "Damascus"
_EmployeeRow("Country") = "Syria"

_DataTable.Add(_EmployeeRow)

Dim _InsertCommand As New SqlCommand(_InsertCommandText, _SqlConnection)
With _InsertCommand.Parameters
.Add("FirstName",SqlDbType.NVarChar, 10, "@FirstName")
.Add("LastName",SqlDbType.NVarChar, 15, "@LastName")
.Add("TitleOfCourtesy",SqlDbType.NVarChar, 25, "@TitleOfCourtesy")
.Add("City",SqlDbType.NVarChar, 15, "@City")
.Add("Country",SqlDbType.NVarChar, 15, "@Country")
End With

_SqlDataAdapter.InsertCommand = _InsertCommand
_SqlDataAdapter.Update(_DataSet, "Employees")

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

تعديل بيانات من جدول ما باستخدام الـ( Dataset ) والـ( DataAdapter ) :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _QueryCommandText As String = "Select * From Employees " & _
"Where TitleOfCourtesy = 'BasharVS'"
Dim _UpdateCommandText As String = "Update Employees Set " & _
"TitleOfCourtesy = @TitleOfCourtesy Where EmployeeID = @EmployeeID"

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter(_QueryCommandText, _SqlConnection)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Employees")

Dim _DataTable As DataTable = _DataSet.Tables("Employees")

_DataTable.Rows(0)("TitleOfCourtesy") = "BVS"

Dim _UpdateCommand As New SqlCommand(_UpdateCommandText, _SqlConnection)
With _UpdateCommand.Parameters
.Add("EmplyeeID", SqlDbType.Int, 4, "@EmplyeeID").SourceVersion = DataRowVersion.Original
.Add("TitleOfCourtesy",SqlDbType.NVarChar, 25, "@TitleOfCourtesy")
End With

_SqlDataAdapter.UpdateCommand = _UpdateCommand
_SqlDataAdapter.Update(_DataSet, "Employees")

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

يجب علينا ملاحظة إعداد الخاصية ( SourceVersion ) للمعامل الذي يمثل قيمة المعرف بالنسبة للشرط الذي تقوم عليه عملية التعديل، إعداد هذه الخاصية يخبر عملية التعديل بأن مقارنة المعرفات تعتمد على نسخة الجدول القديمة ( المقصود بالقديمة أي البيانات قبل التعديل فلو قامنا بتغير المعرف لإحدى السجلات سوف يحدث مشكلة في تتبع التعديل على قاعدة البيانات والسبب عدم تقابل معرفين بين الجدول الموجود في الـ( DataSet ) والجدول الموجود في قاعدة البيانات )، وبمناسبة الحديث عن هذه الخاصية فيجب أن أخبرك أنها الحل الأفضل لحدوث أخطاء مثل المذكورة وخصوصاً مع الجدوال التي تحوي ( PrimaryKey ) .

حذف بيانات من جدول ما باستخدام الـ( [Dataset ) والـ( DataAdapter ) :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _QueryCommandText As String = "Select * From Employees"
Dim _DeleteCommandText As String = "Delete From Employees Where EmployeeID = @EmployeeID"

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter(_QueryCommandText, _SqlConnection)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Employees")

Dim _DataTable As DataTable = _DataSet.Tables("Employees")

For Each ERow As DataRow In _DataTable.Rows
If (ERow("FirstName") = "Bashar") And (ERow("LastName") = "Rabatt") Then
ERow.Delete() : Exit For
End If
Next ERow



Dim _DeleteCommand As New SqlCommand(_DeleteCommandText, _SqlConnection)
With _UpdateCommand.Parameters
.Add("EmplyeeID", SqlDbType.Int, 4, "@EmplyeeID")
End With

_SqlDataAdapter.DeleteCommand = _DeleteCommand
_SqlDataAdapter.Update(_DataSet, "Employees")

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

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

كملاحظة : يجب تحديث معلومات الكائن ( CommandBuilder ) في كل مرة تقوم فيها بالاستعلام عبر جملة استعلام مختلفة وطبعاً هذا الشرط قائم على الـ( CommandBuilder ) التابع للـ( DataAdapter ) المستخدم في معالجة الاستعلامات .

تصريح الـ( CommandBuilder ) يتم بواسطة :

Dim _SqlCommandBuilder As New SqlCommandBuilder( _SqlDataAdapter )

لنرى مثال :

Imports System
Imports System.Data
Imports System.Data.SqlClient

Module UsingDatasetAndDataAdapter

Sub Main
Dim _ConnectionString As String = "Server=.\SqlExpress; Integrated Security=True; Database=Northwind"

Dim _SelectCommandText As String = "Select * From Employees"

Dim _SqlConnection As SqlConnection

Try
_SqlConnection = New SqlConnection(_ConnectionString)
_SqlConnection.Open()

Dim _SqlDataAdapter As New SqlDataAdapter_SelectCommandText, _SqlConnection)

Dim _SqlCommandBuilder As New SqlCommandBuilder(_SqlDataAdapter)

Dim _DataSet As New DataSet()

_SqlDataAdapter.Fill(_DataSet, "Employees")

Dim _DataTable As DataTable = _DataSet.Tables("Employees")

_SqlDataAdapter.Update(_DataSet, "Employees")

Catch SqlEx As SqlException
MsgBox(SqlEx.ToString())
Catch Ex As Exception
MsgBox(Ex.ToString())
Finally
_SqlConnection.Close()
_SqlConnection.Dispose()
End Try
Console.ReadLine()
End Sub

End Module

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

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

بالتوفيق :)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

وقت لهذا الكم من المعلومات و الترتيب الرائع لتوصيل المعلومة ...

جزاك الله عنا الف الف خير

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

إنتقاء البيانات ( Filtering Data )

ذكرنا في درسنا السابق أننا سنرى كيفية انتقاء البيانات بدون استخدام كائنات إضافية أي فقط باستخدام جدول ما ( Table ) أو جدول تابع لبنك معلومات ما ( Dataset ) .

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

تعبير شرط الانتقاء : هو نص يمثل شرط آحادي، ثنائي أو متعدد وبشكل عام يعتمد على رموز وكلمات الـ( Sql ) المحجوزة فإذا لم تكن على دارية بها راجع المقال الأول والذي يشرح جميع أشكال التعبير الشرطي .

جواب الشرط : يدل على تحقق أو عدم تحقق مقارنة ما، فإذا كان الشرط محقق فالجواب ( محقق )=( True ) وإذا كان الشرط غير محقق فالجواب ( غير محقق )=( False ) .

شرط آحادي : هو النص الذي يدل على مقارنة شرط واحد، مثال ( "UserID = 'BasharVS'" )

شرط ثنائي : هو النص الذي يدل على مقارنة شرطين، مثال ( "UserID = 'BasharVS' And Password = '0000'" )

شرط متعدد : هو النص الذي يدل على مقارنة ثلاثة شروط أو أكثر، مثال ( "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'" )

والان نعود لعمليتنا ( Select ) التي تنتمي إلى كائن الـ( DataTable ) يمكن استدعاء هذه العملية بأربعة طرق وأول تلك الطرق :

استدعاء مباشر، والتي تعيد السجلات بدون أي شرط :

Dim FRows As System.Data.DataRow() = System.Data.DataTable.Select()

استدعاء العملية ( Select ) بتمرير تعبير الانتقاء ( شرط ما ) :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression)

استدعاء العملية ( Select ) بتمرير تعبير الانتقاء ( شرط ما ) وبتمرير صيغة ترتيب السجلات :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort)

استدعاء العملية ( Select ) بتمرير كل من تعبير الانتقاء وصيغة ترتيب السجلات وحالة السجل :

حالات السجل :

DataViewRowState.Added : السجلات المضافة . ( العدد المكافئ 4 )

DataViewRowState.CurrentRows : السجلات الحالية . ( العدد المكافئ 22 )

DataViewRowState.Deleted : السجلات المحذوفة . ( العدد المكافئ 8 )

DataViewRowState.ModifiedCurrent : السجلات الحالية المعدلة. العدد المكافئ 16 )

DataViewRowState.ModifiedOriginal : السجلات الأصلية المعدلة . ( العدد المكافئ 32 )

DataViewRowState.None : لاشيء . ( العدد المكافئ 0 )

DataViewRowState.OriginalRows : السجلات الأصلية . ( العدد المكافئ 42 )

DataViewRowState.Unchanged : السجلات التي لم يحدث لها أي تغير . ( العدد المكافئ 2 )

لاحظ أيضاً أن مجموع ( Added و ModifiedCurrent و Unchanged ) أي ( 4 + 16 + 2 ) يساوي ( 22 ) أي ( CurrentRows ) :

وطبعاً ( Added ) أي مضافة حديثاً وتعد من السجلات الحالية، و ( ModifiedCurrent ) والسجلات الحالية المعدلة تابعة للسجلات الحالية، و ( Unchanged ) تابعة لكلا أشكال التمييز ولذلك تعد أيضاً من السجلات الحالية ( علماً أنها غير محددة فهي تلتحق بالسجلات الأصلية أيضاً ) .

ولاحظ أيضاً أن مجموع ( Deleted و ModifiedOriginal و Unchanged ) أي ( 8 + 32 + 2 ) يساوي ( 42 ) أي ( OriginalRows ) :

( Deleted ) لماذا لم تدخل على السجلات الحالية ؟ السبب أنك إذا حذفت شيء من الـ( DataTable ) لن يحدث مشكلة عند عملية البحث أو عند تنفيذ عملية ( Update ) وذلك لأن المقارنة تتم على سجلات قاعدة البيانات فإذا لم يعدل سجل من سجلات قاعدة البيانات لن يحدث مشكلة لكن إذا قمت بتعديل سجل غير موجود في قاعدة البيانات فبالتأكيد سيحدث خطاً وذلك لأن غير قادر على تغير صفات عنصر غير موجود أصلاً !

نعود ( Deleted ) تعد من السجلات الأصلية، ( ModifiedOriginal ) السجلات الأصلية المعدلة فهي من السجلات الأصلية، و ( Unchanged ) كما ذكرنا سابقاً أنها تنتمي إلى شكلين التمييز وبذلك فتعد من السجلات الأصلية أيضاً .

ويمكن دمج عدة حالات لمعالجة سجلات كل من النسخة الأصلية والنسخة الحالية باستخدام العبارة المنطقية ( Or ) أو يمكنك أن تمرر قيمة عدد صحيح يمثل مجموع الأعداد المكافئة لعدة حالات، مثال :

حالة من الحالات الموجودة :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort, DataViewRowState.OriginalRows)

تمرير عدة حالات مدموجة بواسطة العبارة ( Or ) :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim RecStates As DataViewRowState = DataViewRowState.ModifedCurrent Or DataViewState.ModifedOriginal
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort, RecStates)

تمرير عدة حالات مدموجة بواسطة عدد صحيح يمثل مجموع الأعداد المكافئة للحالات :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim RecStates As Int32 = 48
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort, RecStates)

أو بشكل مباشر :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort, 48)

أو تمرير متغير يمثل مُرقم حالة، عدة حالات من حالات السجل :

Dim FilterExpression As String = "UserArea In ('Design', 'Programming') And UserLevel > 4 And Permissions = 'Full'"
Dim Sort As String = "EmployeeID ASC"
Dim RecStates As DataViewRowState = 48
Dim FRow As System.Data.DataRow() = System.Data.DataTable.Select(FilterExpression, Sort, RecStates)

بعض منا سيسأل ( لماذا لا نقوم باستيراد بيانات بنفس الطريقة أي بنفس شرط الانتقاء وبنفس صيغة الترتيب ؟ ) أليست آلية الاتصال المباشر أفضل ؟

الجواب - نعم لكن بشروط، تكلمنا عن هذه الشروط في درسنا السابق وهي أن عملية الاتصال المباشر أفضل بالنسبة لقواعد البيانات المحلية أما بالنسبة لقواعد البيانات الغير المحلية أي التي تحتاج لاتصال بعيد فمن الأفضل استخدام كائنات مثل الـ( Dataset ) والـ( DataTable ) وذلك لتسهيل عملية المعالجة وتوفير الوقت والحجم المعلومات المتبادلة بين الخادم والعميل .

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

1 - استئجار عامل يساعدك في نقل الكرات من وإلى المستودع .

2 - نقل مايمكنك نقله من كرات لتوفر على نفسك عناء الذهاب إلى المستودع مرة أخرى .

3 - شراء آلة تصل بين محلك والمستودع تقوم بتبادل الكرات عبرها .

4 - شراء صندوق يتسع لـ( ثلاثين كرة ) وتعبئته بمقدار عشرين كرة بألوان مختلفة تلبيتاً لطلب الصغار .

فكر بالطريقة الأولى -ستجد أنك- تحتاج مصروف أكبر :( لذلك ( غير مقبولة ) .

ــــ بالطريقة الثانية -ستجد أنك- ستتعب نفسك بحمل الكرات وتجد صعوبة في بيعها أيضاً :( لذلك ( غير مقبولة ) .

ــــ بالطريقة الثالثة -ستجد أنك- ستدفع مبالغ كبيرة لتحصل على هذه الآلة وأيضاً ستدفع بعض المبالغ لقاء تصليح إحدى الأعطال وفي النهاية عليك دفع فاتورة كهرباء أكبر !! :'-( لذلك ( غير مقبولة!! ) .

ــــ بالطريقة الرابعة -ستجد أنك- ستتعب بعض الشيء لكنك ستعمل بشكل منظم ومريح واقتصادي ;) .

من الطرق الأربع نرى أن الطريقة الرابعة هي الأضمن من حيث الراحة ( بشكل جزئي )، التوفير والتنظيم .

وهنا تكمن فكرة انتقاء السجلات( الكرات ) عبر العملية Select والتي تؤديها أنت :)، فعلى سبيل المثال : طفل يريد أن يشتري كرة حمراء اللون مالذي ستفعله ؟ هل ستبحث عنها عند سؤاله أم سترتب جميع الألوان بأماكن محددة لها ؟

يمكنني أن أفعل أي منهما ؟

صحيح لكن فرزها بأماكن محددة يختصر عملية البحث مما يسرع البيع أيضاً ;)

post-178281-1258412279_thumb.jpg

استخدام عملية ( Select ) التالية لجلب الكرات التي تحمل اللون الأخضر :

Dim FilterExpression As String = "SphereColor = Green"
Dim FRow As System.Data.DataRow() = CurrentSphereTable.Select(FilterExpression)

فكرة استدعاء هذه العملية بسيطة جداً لكن عليك أن تستغلها في الوقت والمكان المناسب وإلا سيكون عليك التخلي عنها واستخدام كائنات إضافية كالـ( BindingSource ) والذي سنتحدث عنه في الدرس التالي وسنرى وجهة الاختلاف بينهما أي ( بين العملية ( Select ) والكائن ( BindingSource ) وفاذدته ) .

في المرفقات مشروع بسيط عن درسنا هذا .

FilterProject.zip

بالتوفيق ;)

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
آلسلام عليكم ورحمه آلله وبركآته .. ,

شرح أكثر من رآئع و تنسيق جميل ..

بآرك الله فيك ..

وبإنتظآر بقية آلدروس

/

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

وقت لهذا الكم من المعلومات و الترتيب الرائع لتوصيل المعلومة ...

جزاك الله عنا الف الف خير

شكراً لاهتمامكم وابداء رأيكم، أرجو أن تعم الفائدة على الجميع :)

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

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

موضوع اكثر من رائع

و متمييز

أعجز عن شكري لك

و حبذا لو تحوله الى كتاب للرجوع اليه مرارا

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الـ( BindingSource ) لا يمكنني ترجمة اسم هذا الكائن بشكل حرفي ولذلك سنجد له اسم مناسب وليكن( منظم مصادر البيانات ).

ينتمي إلى المرجع ( System.Windows.Forms )

تصريحه يعتمد على ثلاثة أشكال :

تصريح مباشر بدون إعداد أي من الخصائص الأساسية :

Dim _BindingSource As New BindingSource()

تصريح كائن ( BindingSource ) جديد وتعين حاويته :

Dim _BindingSource As New BindingSource(Me.Container)

تصريح كائن ( BindingSource ) جديد وتحديد مصدر البيانات والعنصر المستهدف من تلك البيانات .

Dim _DataTable As New DataTable("People")
Dim _BindingSource As New BindingSource(_DataTable, "People")

أو

Dim _DataSet As New DataSet("FCS")
Dim _BindingSource As New BindingSource(_DataSet, "People")

لهذا الكائن عدة استخدمات منها القراءة بشكل حر أي الانتقال بين السجلات باتجاهين مما يجعله شبيه بالـ( DataReader ) لكن الـ( DataReader ) يقرأ البيانات بشكل مباشر متسلسل بجهة واحدة ( إلى الامام ) أما الـ( BindingSource ) فهو يقرأ البيانات بشكل منفصل متسلسل باحدى الاتجاهين اي ( إلى الامام أو الخلف ) والمميز بهذا الكائن هو دعمه للخاصية ( Filter ) ممايساعدك على تحصيل نتائج استعلام شرطي بشكل منفصل .

post-178281-12593342241481_thumb.jpg

وكما ذكرنا في درسنا السابق أن المقارنة ستكون بين العملية ( Select ) والتي تنتمي الى جدول ما والكائن ( BindingSource ) ولذلك تعالوا نرى الفرق بينهما لتكتمل فكرة هذا الكائن بالنسبة لقضية الانتقاء وإجرائته الأساسية :

post-178281-12593342355205_thumb.jpg

كما نرى من صورة المقارنة السابقة أن العملية ( Select ) تعيد ( سجل أو عدة سجلات في آن واحد ) أما الـ( BindingSource ) فيكتمل عمل الانتقاء بوضع حدود لمجال القراءة وهكذا كما هو موضح بالنسبة للصورة السابقة لكن إذا كانت جملة الشرط ( "SphereColor = Blue" ) لن يكون هناك مجال والسبب أن لكل كرة زرقاء مكان مبعثر وغير مرتب على التتالي بالنسبة للكرات الزرقاء الآخرى، فاسؤال هنا :

هل يتم الوثب ( القفز ) من مكان إلى أخر بحسب ترتيب البيانات لتحصيل السجلات المراد تطبيق خاصية الانتقاء عليها ؟

البعض منا يظن أن العملية ( Select ) هي أيضاً العامل الأساسي في انتقاء البيانات عبر الـ( BindingSource ) والسبب أننا سنرسل إما ( DataSet ) ونخبر الـ( BindingSource ) عن الجدول المراد تنظيم بياناته أو سنرسل ( DataTable ) أي جدول، وبذلك نرى أننا نعالج بيانات الجدول أي ( DataTable ) في كلا الحالتين أي بارسال ( DataSet ) أو ( DataTable )، ولكن هل العملية ( Select ) هي العامل الأساسي في انتقاء البيانات عبر الـ( BindingSource ) ؟ فكر بها، جرب الـ( BindingSource ) مع كائنات آخرى وعلى سبيل المثال مصفوفة عددية، مصفوفة خلايا ( Classes ) أو مصفوفة تراكيب ( Structures ) بدون أي تعديل على الكائن ( BindingSource ) جرب إعداد الخاصية ( Filter ) بانتقاء بعض من بيانات إحدى المصفوفات لترى أنه ليس هناك من عملية مكتملة أو بالآحرى فكرة انتقاء البيانات لاتعمل :(

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

( Filter ) = ( Gets or sets the expression used to filter which rows are viewed )

يعني بصريح العبارة ( اقرأ أو اكتب التعبير ( التعبير الشرطي ) المستخدم في انتقاء السجلات المعروضة ( المراد عرضها )) وطبعاً العامل الأساسي هو العملية ( Select ) smile.gif ولذلك يمكننا اعتبار منظم مصادر البيانات على أنه جسر متحرك مساعد لانتقاء البيانات، والفائدة منه هو عرض البيانات بشكل مفرد ( أي عرض معلومات سجل واحد في عدة كائنات ( تحكمات ) مناسبة ) البعض يستخدمه على الـ( DataGridView ) وبنظر بعض الأخوة الكرام أنه ليس هناك من أسباب وجيهة تحفز على ذلك :( ولكني أخالفهم الرأي في حال كان التطبيق يعتمد في الدرجة الثانية على عمليات الانتقاء smile.gif .

بعد أن رأينا وحللنا عمل الـ( BindingSource ) تعالوا نتعرف على بعض من خصائصه وعملياته :

الخصائص :

AllowEdit : قراءة قيمة منطقية تحدد صلاحية تعديل البيانات الموجود في قائمة العناصر .

AllowNew : قراءة أو وضع قيمة منطقية لتحديد صلاحية إضافة عناصر جديدة إلى قائمة العناصر .

AllowRemove : قراءة أو وضع قيمة منطقية لتحديد صلاحية حذف عنصر من عناصر القائمة .

Container : الحاوية للـ( BindingSource ) .

Count : عدد العناصر الموجودة في القائمة .

Current : العنصر الحالي أو الذي يملك التركيز ( لاحظ موقعه من صورة المقارنة السابقة ) .

DataMember : التحديد بقيمة نصية اسم القائمة المراد تنظيم بياناتها بواسطة الـ( BindingSource ) من مصدر البيانات.

DataSource : قراءة أو وضع مصدر بيانات لهذا الـ( BindingSource ) .

Filter : خاصية الانتقاء والتي تقبل قيمة نصية تعبر عن جملة شرطية .

IsFixedSize : قراءة قيمة منطقية تعبر عن حالة حجم القائمة ( متغير، غير متغير ) .

IsReadOnly : قراءة قيمة منطقية تعبر عن حالة البيانات بالنسبة للقراءة ( للقراءة فقط ( التعديل ممنوع )، ليست للقراءة فقط ( التعديل مسموح، الخاصية ( AllowEdit ) محققة ))) .

IsSorted : قراءة قيمة منطقية للاستعلام عن حالة ترتيب البيانات ( مرتبة، غير مرتبة ) .

IsSynchronized : أيضاً قيمة منطقية في حال كانت محققة تعبر عن وجود تزامن في الوصول إلى البيانات، وفي حال لم تكن محققة تعبرعن وصول مباشر إلى البيانات أي بدون تزامن .

Item : لقراءة أو وضع عنصر من عناصر القائمة بشرط تمرير رقم العنصر عبر هذه الخاصية أي على سبيل المثال ( (Item(0 ) .

List : قائمة العناصر أو قائمة البيانات المصدرية .

Position : الاستعلام أو وضع مكان توضع رأس القراءة tongue.gif رقم ترتيب العنصر الحالي بالنسبة للقائمة .

RaiseListChangedEvents : قراءة أو كتابة قيمة منطقية تمنع أو تسمح للحدث ( ListChanged ) التابع للـ( BindingSource ) بالانفجار أو عدم الانفجار !! في حال تم حدوث أي تغير على القائمة .

Sort : قراءة أو وضع قيمة نصية تعبر عن شكل ترتيب بيانات القائمة .

SupportsAdvancedSorting : قراءة قيمة منطقية تعبر عن حالة دعم الترتيب المتقدم بالنسبة لمصدر البيانات ( هل الترتيب متقدم ويقبل عدة حقول ( أعمدة Columns ) أم لا ؟ ) .

SupportsFiltering : قراءة قيمة منطقية تعبر عن حالة دعم صدر البيانات للانتقاء ( مدعوم، غير مدعوم ) .

SupportsSearching : قراءة قيمة منطقية تحدد ما إذا كانت عملية البحث ( Find ) مدعومة من قبل مصدر البيانات .

SupportsSorting : قراءة قيمة منطقية تعبر عن حالة دعم مصدر البيانات للترتيب ( مدعوم، غير مدعوم ) .

الإجراءات والعمليات :

Add :إضافة عنصر جديد إلى القائمة الداخلية ( مصدر البيانات ) .

AddNew : إضافة عنصر جديد إلى قائمة عناصر الـ( BindingSource ) .

ApplySort : ترتيب بيانات مصدر البيانات بحسب شكل أو وصف الترتيب المستخدم في ترتيب عناصر الـ( BindingSource ) .

CancelEdit : إلغاء عملية التعديل الحالية ( العملية القائمة عند وقت استخدام هذا الإجراء ) .

Clear : حذف جميع عناصر قائمة الـ( BindingSource ) .

Contains : عملية تستخدم للتأكد من وجود عنصر وحيد أو عنصر يتألف من عدة عناصر تعيد قيمة منطقية ( محققة في حال وجد العنصر المراد التأكد منه، غير محققة في حال عدم وجود ذلك العنصر ) .

CopyTo : نسخ عناصر قائمة الـ( BindingSource ) إلى مصفوفة .

EndEdit : تصريح انتهاء تعديل عناصر مصدر البيانات .

Find : تحدثنا عنها سابقاً ومهمتها إيجاد عناصر بشروط معينة .

Insert : إضافة عنصر جديد إلى قائمة عناصر الـ( BindingSource ) .

MoveFirst : الانتقال إلى العنصر الأول ( 0 ) ليتم قراءة بياناته عبر الخاصية ( Current ) .

MoveLast : الانتقال إلى العنصر الأخير ( ++ ) ليتم قراءة بياناته عبر الخاصية ( Current ) .

MoveNext : الانتقال إلى العنصر الذي يلي العنصر الحالي ( +1 ) ليتم قراءة بياناته عبر الخاصية ( Current ) .

MovePrevious : الانتقال إلى العنصر الذي يسبق العنصر الحالي ( -1 ) ليتم قراءة بياناته عبر الخاصية ( Current ) .

Remove : حذف عنصر محدد من قائمة عناصر الـ( BindingSource ) .

RemoveAt : حذف عنصر من عناصر قائمة الـ( BindingSource ) بتمرير رقم العنصر عبر العملية .

RemoveCurrent : حذف العنصر الحالي من قائمة عناصر الـ( BindingSource ) .

RemoveFilter : حذف جملة الشرط المستخدمة في انتقاء البيانات .

RemoveSort : حذف شكل الترتيب المستخدم لترتيب البيانات .

ResetAllowNew : تفعيل الخاصية ( AllowNew ) .

قبل أن ننهي هذا الدرس علينا أن نرى شيء صغير وهو ربط الآدوات بالكائن ( BindingSource ) عبر كائنات الربط ( Bindings )، لربط التحكمات التي تدعم ( DataBindings ) علينا إما إضافة كائن ربط جديد من نافذة التصميم أو بواسطة ( Code ) برمجي كالتالي :

Dim _DataBinding As New Binding("Text", PeopleBindingSource, "ID", False, DataSourceUpdateMode.Never, DBNull.Value, "0000")
TextBox.DataBindings.Add(_DataBinding)

شرح ماسبق :

المُعامل الأول ( اسم الخاصية PropertyName ) : كما نعلم أن الخاصية ( Text ) التي يتم بواسطتها تحديد قيمة نصية تعرض بواسطة إحدى التحكمات الداعمة للنصوص المرئية .

المُعامل الثاني ( مصدر البيانات DataSource ) : يقبل أي كائن له عناصر قابلة للربط .

المُعامل الثالث ( اسم الحقل المستهدف ColumnName ) : يقبل قيمة نصية تدل على اسم الحقل المراد عرض القيمة المقابلة للسجل الحالي بالنسبة له .

المُعامل الرابع ( تفعيل التنسيق FormattedEnabled ) : قيمة منطقية تعبر عن حالة تنسيق القيمة ( محققة في حال كنت تريد استخدام التنسيق، غير محققة في حال لم تكن تريد تنسيق القيمة ) .

المُعامل الخامس ( وضع تعديل مصدر البيانات DataSourceUpdateMode ) : هناك ثلاث قيمكن تمريرها إحداها عبر هذه المُعامل :

1* DataSourceUpdateMode.Never
2* DataSourceUpdateMode.OnPropertyChanged
3* DataSourceUpdateMode.OnValidation

1* أبداً : التغاضي عن تعديل بيانات المصدر .

2* عند تغير قيمة خاصية التحكم المرتبط : كما رأينا من الـ( Code ) السابق أن الربط يتم مع الخاصية ( Text ) للـ( TextBox )، وبذلك نفهم أن عند تغير قيمة الخاصية ( Text ) لذلك الـ( TextBox ) يتم تعديل القيمة القديمة من مصدر البيانات .

3* عند التأكد أو التحقق : بعد التأكد من صحة قيمة خاصية التحكم المرتبط يتم تعديل القيمة القديمة من مصدر البيانات .

المُعامل السادس ( القيم الغير معرفة NullValue ) : تعويض القيم الغير معرفة بقيمة كائن ما، تقبل أي كائن يمكن للخاصية المستهدفة معالجته .

المُعامل السابع ( التنسيق Format ) : نص يمثل شكل تنسيق القيمة المقروءة، بملاحظة أنه لا يتم تطبيق هذا التنسيق في حال كانت قيمة ( تفعيل التنسق ) غير محققة .

يمكننا أيضاً أن نضيف ( DataBinding ) بدون تصريحه بشكل فرعي :

TextBox.DataBindings.Add("Text", PeopleBindingSource, "ID", False, 2, DBNull.Value, "0000")

[Code]

انتهينا ! tongue.gif، في المرفقات مشروع بسيط عن درسنا هذا لاكمال الفكرة ;)

post-178281-12593342418193_thumb.jpg

UsingBindingSource.zip

[size=7][color=#2e8b57]كل عام وأنتم بخير[/color] [/size]smile.gif

تم تعديل بواسطه Bashar Rabat
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

جزاك الله كل خير حقاّ اخي أبدعت وكفيت ووفيت

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

سلام عليكم

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .