الوصول إلى قواعد بيانات من لغة C# باستخدام ADO
الوصول إلى قواعد بيانات من لغة C# باستخدام ADO
مقدمة حول ADO.NET
ADO.NET ممكن تستخدم مع أربعة انظمة ادارة قواعد بيانات (client namespaces) مختلفة: SQL Server ، Oracle، ODBC ، و OLEDB.
Namespaces:
الكلاسات Classesوالواجهات interfaces التالية تستخدم في NET. للوصول للبيانات:
- System.Data جميع الكلاسات التي تستخدم للوصول إلى البيانات
- System.Data.Common : الكلاسات التي تمت مشاركتها (أو تجاوزها) بواسطة مزودي البيانات بشكل فردي.
- System.Data.Odbc
- System.Data.OleDb
- System.Data.Oracle
- System.Data.SqlClient
- System.Data.SqlTypes : خاص أنواع البيانات SQL Server data types
في هذا الكتاب سيتم استخدام SQL Server
الكلاسات المهمة التي سيتم استخدامها في هذا الدروس:
- DataSet: صمم من أجل استخدامه في حالة عدم الإتصال. ويحتوي على مجموعة من DataTables التي ترتبط بالجدوال والعلاقات بين هذه الجداول.
- DataTable: يحتوي على عمود (DataColumn) واحد أو اكثر. عند استخدمه سيحتوي بيانات التي عباره عن على الأقل صف واحد (DataRows).
- DataRow: مجموعة من القيم تشبه صفوف جداول.
- Data Column: هي كائن يحتوي على تعريف اسم ونوع البيانات الحقول.
الكلاسات لتحديد واتصال بالبيانات:
- SqlCommand: يستخدم للتعامل مع جمل SQL statement و استدعاء الاجراءات Procedure calss
- SqlCommandBuilder يستخدم لانشاء اوامر SQL مثل INSERT, UPDATE, DELETE من عبارة SELECT
- SqlConnection يستخدم للاتصال بقاعدة بيانات
- SqlDataAdapter يستخدم للاحتفاظ ب اوامر select, insert, update, and delete التي تستخدم بعد ذلك للتعامل مع DataSet
- SqlDataReader: يستخدم لقراءة البيانات فقط..
- SqlParameter: لتعريف الباراميترات التي تستخدم في Procedures
التطبيق العملي:
سنأخذ مثال حقيقي من أجل ان نفهم طرق الربط والتعديل والاستعلام لقواعد البيانات. وهذا المثال هو انشاء برنامج بسيط لبيع الكتب بالتالي نحتاج أولا تصميم قاعدة بيانات BOOKS والتي تحتوي على الجداول التالية:
لأنشاء قاعدة البيانات والجداول:
https://docs.microsoft.com/en-us/sql/t-sql/statements/create-database-sql-server-transact-sql
الاتصال بقاعدة بيانات:
using System.Data.SqlClient;
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
zahersql هو الخادم الذي يحتوي على قاعدة البيانات BOOKS حيث اسم الكمبيوتر zaher . أما integrated security=SSPI يدل على أن نوع الامن للوصول لقاعدة البيانات هو Windows Authentication.
وافضل طريقة للاتصال هو:
try
{
using (SqlConnection conn = new SqlConnection ( source ))
{
// Open the connection
conn.Open ( ) ;
// Do something useful
// Close it myself
conn.Close ( ) ;
}
}
catch (Exception e)
{ // Do something with the exception here...
}
Command: هو عبارة عن نص يحتوي على عبارات SQL وممكن ان يحتوي على Procedure او اسم جدول الذي سيرجع كل أو جزء صفوف واعمدة جدول ما.
مثال:
using System.Data.SqlClient;
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "SELECT * FROM Authors";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlCommand cmd = new SqlCommand(Authortable, conn);
كلاس Command يحتوي على خاصية اسمها CommandType التي تستخدم لتعريف الكلاس هل خو عبارة عن عبارة SQL ام Procedure أو جدول كامل Full table . للتفصيل انظر الجدول التالي:
Example |
Command Type |
|
Text (default) |
|
StoredProcedure |
|
TableDirect |
تنفيذ الأمر Executing Commands:
بعد تعريف الCommand تحتاج إلى تنفيذه Exceute. هناك عدت طرق لتنفيذ الامر يعتمد على ماذا تريد أن يرجع الأمر:
- ExecuteNonQuery() لتنفيذ الأمر بدون ارجاع أي مخرجات.
- ExecuteReader() تنفيذ الأمر مع ارجاع من نوع IDataReader.
- ExecuteScalar() تنفيذ الأمر مع ارجاع قيمة واحدة.
مثال على استخدام ExecuteNonQuery
using System.Data.SqlClient;
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "UPDATE Authors SET FirstName=’JNA’ WHERE FirstName= ‘Ahmed’ ";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlCommand cmd = new SqlCommand(Authortable, conn);
int rowsReturned=cmd. ExecuteNonQuery();
Console.WriteLine("{0} rows returned.", rowsReturned);
conn.Close()
سترجع ExecuteNonQuery عدد الصفوف التي تأثرت بذلك الأمر.
مثال على استخدام ExecuteReader:
using System.Data.SqlClient;
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "SELECT firstName, lastName FROM Authors";
SqlConnection conn = new SqlConnection(source);
conn.Open();
SqlCommand cmd = new SqlCommand(Authortable, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("FirstName: {0} LastName: {1}" , reader[0] , reader[1]);
}
Console.ReadKey();
هذه الطريقة سترجع نوع بيانات data reader object بحيث هذا الobject ممكن ارجاع قيمه باستخدام التكرار مثل الظاهر في المثال اعلاه. ونتائج البرنامج موضحة في الشكل التالي:
مثال على استخدام ExecuteScalar
using System.Data.SqlClient;
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "SELECT count(*) FROM Authors";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlCommand cmd = new SqlCommand(Authortable, conn);
Object o= cmd. ExecuteScalar ();
Console.WriteLine(o);
يستخدم فقط في حالة نتيجة عبارة SQL هي ارجاع قيمة واحدة فقط مثل هذا المثال فإن المخرج هو 4 وهي عدد صفوف جدول Authors.
عمليات السجلات:
سنتطرق هنا إلى العمليات التي ستجرى على الجداول بالأمثلة وهي إضافة سجل وتعديل سجل وحذف سجل.
- إضافة سجل
اذا اردنا اضافة مؤلف جديد اسمه Samear Hadi
string AddAuth = "INSERT INTO Authors(AuthorID,firstName,lastName) Values (@ID,@fname,@lname)";
SqlCommand cmdAdd = new SqlCommand(AddAuth, conn);
cmdAdd.Parameters.AddWithValue("ID", 5);
cmdAdd.Parameters.AddWithValue("fname", "Sameer");
cmdAdd.Parameters.AddWithValue("lname", "Hadi");
try
{ cmdAdd.ExecuteNonQuery();
}
catch (SqlException ex)
{ Console.WriteLine("Error- It can not Add "); }
يجب ان يكون رقم المؤلف الجديد غير مستخدم في الجدول.
2. حذف سجل:
اذا اردنا حذف المؤلف رقم 5
string Delet_Auth = "DELETE FROM Authors where AuthorID = @ID";
SqlCommand cmddel = new SqlCommand(Delet_Auth, conn);
cmddel.Parameters.AddWithValue("ID", 5);
try
{ cmddel.ExecuteNonQuery(); }
catch (SqlException ex) {
Console.WriteLine("Error- ") ;
}
3. تعديل لقيم سجلات:
مثال: اذا اردنا تعديل اسم المؤلف صاحب رقم 3 إلى Jna Zaher فإننا سنقوم بتنفيذ الأمر التالي:
string str = "UPDATE Authors SET firstName =@fname, lastName=@lname WHERE AuthorID=@ID";
SqlCommand cmd_Updat_Auth = new SqlCommand(str, conn);
cmd_Updat_Auth.Parameters.AddWithValue("ID", "3");
cmd_Updat_Auth.Parameters.AddWithValue("fname", "Jna");
cmd_Updat_Auth.Parameters.AddWithValue("lname", "Zaher");
try
{ int rowsReturned=cmd_Updat_Auth.ExecuteNonQuery();
Console.WriteLine("{0} rows returned.", rowsReturned);
}
catch (SqlException ex)
{ Console.WriteLine("Error"); }
الواجهات الرسومية وربطها مع قاعدة البيانات
اذا اردنا ان نستخدم بعض الأدوات الواجهات الرسومية وجعلها تتفاعل وربطها مع قاعدة البيانات مثل Textboxesو Button وDataGridView
فإننا أولا سنحتاج إلى SqlDataAdapter و DataSet و Datable .
SqlDataAdapter
عمل كـ جسر بين DataSetو SQL الخادم باسترداد وحفظ بيانات. عند SqlDataAdapterتعبئة DataSet، يقوم بإنشاء الجداول المطلوبة و أعمدة البيانات التي يتم إرجاعها إذا كانت غير موجود مسبقاً. ومع ذلك.
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "SELECT * FROM Authors";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlDataAdapter adap = new SqlDataAdapter(Authortable, conn);
DataSet ds = new DataSet();
adap.Fill(ds, "Authors");
حيث Fill هي دالة لتسترجع بيانات مخزنة في المصدر باستخدام عبارة SELECT
DataSet: وهي مجموعة من الجداول التي توضع في الذاكرة و يقوم المبرمج بعمليات الإضافة و التعديل و الحذف و الإستعلام عليها ثم تطبق هذه العمليات على قاعدة البيانات نفسها و تسمى هذه العملية بالوضع المنفصل لأننا لا نتعامل مع قاعدة البيانات مباشرة و إنما نتعامل مع نسخة من جداولها.
Datable هو كائن يمثل أحد جداول ال Dataset ، اي انك إذا اردت أن تقوم بعملية ما على احد هذه الجداول فعليك أن تنشئ كائن جديد من النوع DataTable
DataTable records = ds.Tables["Authors"];
ربط القاعدة مع DataGridView
فمثلا في مرحلة تصميم الواجهات أضفنا dataGridView1 ونريدها تعرض جدول Author.
dataGridView1.DataSource = ds.Tables["Authors"];
حيث ds هو dataset من المثال السابق. الشكل التالي يبين النتائج:
التنقل بين السجلات وربط القاعدة بTextboxes
ناخذ مثال الظاهر في الشكل التالي:
اولا نقوم بتصميم الواجهة.
افرض أن textBox1 هو مربع النص الذي يظهر الاسم الأول و textBox2 هو مربع النص الذي يظهر الاسم الأخير أما button1 هو First و button2 هو Next و button3 هو Previous و button4 هو Last.
التطبيق:
- ربط textboxes بقاعدة البيانات والجدول.
public partial class Form2 : Form
{
private int rowindex = 0; // تم استخدامه ليكون مساعد ومحدد لرقم سجل الذي تم انتقال إليه
private void Form2_Load(object sender, EventArgs e)
{
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Authortable = "SELECT * FROM Authors";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlDataAdapter adap = new SqlDataAdapter(Authortable, conn);
DataSet ds = new DataSet();
adap.Fill(ds, "Authors");
records = ds.Tables["Authors"];
//تعبئه مربع النصوص بأول سجل من جدول المؤلف إذا احتوى على سجلات
if (records.Rows.Count > 0)
/* records.Rows.Count تساوي 0 اذا كان جدول Authors فارغ*/
{ textBox1.Text = records.Rows[0]["firstName"].ToString();
textBox2.Text = records.Rows[0]["lastName"].ToString();
}
2. ازار التنقل :
- First: الانتقال إلى السجل الأول
private void button1_Click(object sender, EventArgs e)
{ if (records.Rows.Count > 0 )
{ textBox1.Text = records.Rows[0]["firstName"].ToString();
textBox2.Text = records.Rows[0]["lastName"].ToString();
rowindex = 0;
}
}
- Next: للتنقل إلى السجل التالي.
private void button2_Click(object sender, EventArgs e)
{ rowindex++;
if (records.Rows.Count > 0 && rowindex < records.Rows.Count)
{ textBox1.Text = records.Rows[rowindex]["firstName"].ToString();
textBox2.Text = records.Rows[rowindex]["lastName"].ToString();
}
if (rowindex > records.Rows.Count-1) // من أجل أن لا يتعدى رقم السجل الأخير
rowindex = records.Rows.Count-1;
}
- Previous: للانتقال الى السجل السابق
private void button3_Click(object sender, EventArgs e)
{ rowindex--;
if (records.Rows.Count > 0 && rowindex >=0)
{ textBox1.Text = records.Rows[rowindex]["firstName"].ToString();
textBox2.Text = records.Rows[rowindex]["lastName"].ToString();
}
if (rowindex < 0) // من اجل أن لا يسبق أول سجل
rowindex = 0;
}
- Last: الانتقال إلى السجل الأخير
private void button4_Click(object sender, EventArgs e)
{ if (records.Rows.Count > 0)
{ textBox1.Text = records.Rows[records.Rows.Count-1]["firstName"].ToString();
textBox2.Text = records.Rows[records.Rows.Count-1]["lastName"].ToString();
rowindex = records.Rows.Count-1;
}
}
البحث في جداول:
كيفية البحث عن المؤلفين الذين يحتوي اسمهم الأخير على كلمة معينة تكتب في textBox1. اولا تصمم الواجهه في الشكل التالي:
ثم نكتب الكود التالي في حدث TextChanged لtextBox1:
private void textBox3_TextChanged(object sender, EventArgs e)
{ string st = "SELECT * FROM Authors WHERE lastName LIKE '%" + textBox3.Text + "%' ";
SqlDataAdapter searchadap = new SqlDataAdapter(st, conn);
DataSet ds1 = new DataSet();
searchadap.Fill(ds1);
dataGridView1.DataSource = ds1.Tables[0];
}
الربط أكثر من جدول وعرضها في dataGridView1
string source = "server=zaher\\zahersql ;integrated security=SSPI;database=BOOKS";
string Book = "SELECT title, publisherName, edtionNumber, copyright, price FROM Titles ,publishers
WHERE Titles.pubID = publishers.pubID";
SqlConnection conn= new SqlConnection(source);
Conn.Open();
SqlDataAdapter adap = new SqlDataAdapter(Book, conn);
DataSet ds = new DataSet();
adap.Fill(ds );
dataGridView1.DataSource = ds.Tables[0];
المراجع
[1] S. Robinson, C. Nagel, J. Glynn, M. Skinner, K. Watson, and B. Evjen, Professional C#. 2004.
[2] Harvey M. Deitel, P. J. Deitel, T. R. Nieto, C. H. Yaeger, M. Zlatkina, and J. Listfield, C#: How to Program. 2002.
[3] Microsoft, “msdn.microsoft.com.” .
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !