العودة   منتدى رياض الجنة - Riad Al-Ganah > الرياض التقنية > روضة الكورسات والدورات التقنية والعلمية > روضة دورات تقنية الـ .NET بلغاتها المختلفة > دورة .NET 2008 من منتدى فيجوال بيسك للعرب

دورة .NET 2008 من منتدى فيجوال بيسك للعرب مقدم الدورة : أحمد جمال ، نوع الدورة : كتابية مصحوبة بصور ، حالة الدورة : انتهت ، عدد الدروس : 80 درس . مستوى الدورة : من البداية للاحتراف .

إضافة رد

 
أدوات الموضوع انواع عرض الموضوع
  #1  
قديم 03-11-2010, 03:14 PM
الصورة الرمزية khaledbelal
khaledbelal khaledbelal غير متواجد حالياً
مبرمج المنتدى
الادارة تكليف لا تشريف
 
تاريخ التسجيل: Oct 2009
العمر: 34
المشاركات: 3,606
افتراضي الدرس الثالث : عالم ADO.net وما يتعلق به - الجزء الثالث - دورة .net 2008

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

في هذا الدرس سنحاول التعرف على ماهية الوضع المتصل Connected Layer في ADO.net .
يسمح لك الوضع المتصل Connected Layer والذي يعتمد على وجود اتصال مفعل بقاعدة بياناتك اثناء عمليات التعديل بالتعامل مع قاعدة بياناتك من خلال connection للاتصال و command لتنفيذ الاستعلامات اضافة إلى data reader الخاصة بال DataProvider الذي تنوي التعامل معه وفي حالتنا هذه هو ال SQL .

سنقوم الآن بعمل تطبيق بسيط لعرض كافة اسماء الموظفين في قائمة ، لذا قم بالمتابعة معنا خطوة بخطوة :

1- جلب المكتبات التي سوف نتعامل معها وهي في حالتنا هذه System.Data.SqlClient :
C#:
كود PHP:
using System.Data.SqlClient
vb.net:
كود PHP:
Imports System.Data.SqlClient 
2- التعامل مع Connection من اجل الوصول إلى قاعدة البيانات الخاصة بنا وفتحها :
C#:
كود PHP:
SqlConnection cn = new SqlConnection(); 
كود PHP:
           cn.ConnectionString = @"Data Source=AHMED-PC\SQLEXPRESS;Initial Catalog=Employee;Integrated Security=True;Pooling=False";
           
cn.Open(); 
vb.net:
كود PHP:
Dim cn As New SqlConnection() 
كود PHP:
cn.ConnectionString "Data Source=AHMED-PC\SQLEXPRESS;Initial Catalog=Employee;Integrated Security=True;Pooling=False" 
cn.Open() 
*** كيف تعرف ال ConnectionString .
أ- هناك العديد من المواقع التي تقدم لك خدمة معرفة ال ConnectionString مثل موقع : www.connectionstrings.com .
ب- لو كنت تعمل من خلال قاعدة بيانات داخل بيئة عمل .net يمكنك معرفة ال ConnectioString لها باختيارها من قائمة Server Explorer ومن ثم مشاهدة ال Properties بالشكل التالي :



ج- باستخدام اي من أدوات .net الجاهزة والتي سنتعرف على بعض منها في مراحل قادمة .

3- كتابة جملة استعلام بسيطة لطلب كل أسماء الموظفين الأولى + الثانية على شكل fullname بالاضافة إلى العمر - لو لم تفهم هذه الجملة راجع دروس TSQL - :
C#:
كود PHP:
string strSQL "Select [First Name]+[Last Name] as [Full Name], Age From Employee_info";
           
SqlCommand myCommand = new SqlCommand(strSQLcn); 
vb.net:
كود PHP:
Dim strSQL As String "Select [First Name]+[Last Name] as [Full Name], Age From Employee_info" 
Dim myCommand As New SqlCommand(strSQLcn
4- تعريف DataReader لقراءة البيانات وتنفيذها على شكل ExecuteReader :

C#:
كود PHP:
SqlDataReader myDataReader;
           
myDataReader myCommand.ExecuteReader(); 
vb.net:
كود PHP:
Dim myDataReader As SqlDataReader 
myDataReader 
myCommand.ExecuteReader() 
5- الدوران على كافة الحقول ووضعها في ListBox1 :
C#:
كود PHP:
string listItem "";
           while (
myDataReader.Read())
           {
               
listItem"Full Name: " myDataReader["Full Name"].ToString() + " Age: " myDataReader["Age"].ToString();
               
listBox1.Items.Add(listItem);
           } 
vb.net:
كود PHP:
Dim listItem As String "" 
While myDataReader.Read() 
   
listItem "Full Name: " myDataReader("Full Name").ToString() + " Age: " myDataReader("Age").ToString() 
   
listBox1.Items.Add(listItem
End While 
سيكون ناتج تنفيذ هذا الكود شيئاً مثل هذا :



6- اغلاق وسائل الاتصال وعدم تركها مفتوحة :
C#:
كود PHP:
            myDataReader.Close(); 
كود PHP:
  cn.Close(); 
vb.net:
كود PHP:
            myDataReader.Close() 
كود PHP:
           cn.Close() 
*** هناك حل آخر لفتح قاعدة البيانات واغلاقها مباشرة بعد انتهاء تنفيذ المهمة ، اثناء عملك ExecuteReader يمكنك تحديد CommandBehavior يحدث بعد اغلاقها ، يحتوي هذا ال Enum على الخيارات التالية :



الخيار الأول هو فقط ما يهمنا ، في هذه الحالة سيكون شكل الكود بالشكل التالي :
C#:
كود PHP:
myDataReader myCommand.ExecuteReader(CommandBehavior.CloseConnection); 
vb.net:
كود PHP:
myDataReader myCommand.ExecuteReader(CommandBehavior.CloseConnection
هنا لن نقلق مجدداً بشأن اغلاق ال Coonection حيث سيتم اغلاقه تلقائياً بعد كتابة هذا السطر :
C#:
كود PHP:
            myDataReader.Close(); 
vb.net:
كود PHP:
           myDataReader.Close() 
- طبعاً لا تنس أن بامكانك عمل نفس جملة الاستعلام Update او Delete أو Insert بدلاً من Select ، وحسب جملة الاستعلام المطلوبة .

- التعامل مع ConnectionStringBuilder :

يوفر لك هذا الكائن طريقة تفصيلية لبناء ال ConnectioString الخاص بك ، هذا المثال يوضح الأكثر استخداماً :
C#:
كود PHP:
SqlConnectionStringBuilder cnStrBuilder = new SqlConnectionStringBuilder();
            
cnStrBuilder.InitialCatalog "Employee";
            
cnStrBuilder.DataSource = @"(local)\SQLEXPRESS";
            
cnStrBuilder.ConnectTimeout 30;
            
cnStrBuilder.Password "124";
            
cnStrBuilder.UserID "Ahmed";
            
SqlConnection cn = new SqlConnection();
            
cn.ConnectionString cnStrBuilder.ConnectionString;
            
cn.Open(); 
vb.net:
كود PHP:
Dim cnStrBuilder As New SqlConnectionStringBuilder() 
cnStrBuilder.InitialCatalog "Employee" 
cnStrBuilder.DataSource "(local)\SQLEXPRESS" 
cnStrBuilder.ConnectTimeout 30 
cnStrBuilder
.Password "124" 
cnStrBuilder.UserID "Ahmed" 
Dim cn As New SqlConnection() 
cn.ConnectionString cnStrBuilder.ConnectionString 
cn
.Open() 
حيث تجد :

- InitialCatalog لتحديد اسم قاعدة البيانات
- DataSource لتحديد مسار قاعدة البيانات
- ConnectTimeout لتحديد الوقت الذي يمكن استغراقه من اجل محاولة الوصول إلى قاعدة البيانات او ايقاف العملية عند انتهاءه .
- Password كلمة مرور قاعدة البيانات إن وجدت .
- UserID اسم المستخدم لقاعدة البيانات إن وجد .

هناك العديد من العناصر الأخرى أيضاً يمكنك استعراضها من هنا :
http://msdn.microsoft.com/en-us/libr...tringbuilder_m embers.aspx

التعامل مع الفئة Command :

ال Command هي جملة الاستعلام التي نستخدمها لتنفيذ اي نوع من العمليات على قاعدة البيانات ، تنقسم إلى ثلاث انواع رئيسية :

- StoredProcedure
- TableDirect
- Text

في المثال السابق استخدمنا ال Command كجملة استعلام نصية مباشرة Text ، كانت بالشكل التالي مثلاً :
C#:
كود PHP:
string strSQL "Select * From Employee_Info";
SqlCommand myCommand = new SqlCommand(strSQLcn); 
vb.net:
كود PHP:
Dim strSQL As String "Select * From Employee_Info" 
Dim myCommand As New SqlCommand(strSQLcn
أو بهذا الشكل :
c#:
كود PHP:
SqlCommand testCommand = new SqlCommand();
testCommand.Connection cn;
testCommand.CommandText strSQL
vb.net:
كود PHP:
Dim testCommand As New SqlCommand() 
testCommand.Connection cn 
testCommand
.CommandText strSQL 
اثناء التنفيذ قمنا بربطها مباشرة باستخدام ExecuteReader ، في الواقع هناك عدة طرق عدة طرق للتنتفيذ :

ExecuteReader : في حالة كون الناتج عدد كبير من البيانات ، يتم تعريف DataReader وربط الناتج به لقراءته ، وهو ما تعرفنا عليه في مراحل سابقة .
ExecuteNonQuery : في حالة عدم وجود نواتج اصلاً ، مثل تعريف عملية update او Delete حيث الناتج الوحيد هو تنفيذ العملية من عدمه ، سيتم التعرف عليه لاحقاً .
ExecuteScalar : في حالة كون الناتج وحيد ، مثل الاستعلام عن فقط عن الاسم الأول للشخص صاحب الرقم القومي xxxxxx .
ExecuteXmlReader : تنفيذ الناتج واعادته على شكل XML يتم تعريف .XmlReader وربط الناتج به لقراءته ، يمكنك الرجوع إلى دروس XML لمعرفة المزيد عن XmlReader .

- استخدام ال Parameterized Command Objects :

كما لاحظت من الدرس الذي تحدثنا فيه عن ال SQL Injection ، فإن الطريقة التقليدية لجمل الاستعلام تظل خطرة ، لذا نبدا باستخدام Parameters لجمل الاستعلام لدينا ايضاً حتى لو لم نكن نتعامل مع Stored Procedure .

لو أخذنا المثال التالي للتجربة :

C#:
كود PHP:
string strSQL "Select [First Name]+[Last Name] as [Full Name], Age From Employee where ID=" ID;
            
SqlCommand myCommand = new SqlCommand(strSQLcn); 
vb.net:
كود PHP:
Dim strSQL As String "Select [First Name]+[Last Name] as [Full Name], Age From Employee where ID=" ID 
Dim myCommand 
As New SqlCommand(strSQLcn
ستجد اننا قادرين بمبادئ ال SQL Injection من اختراق هذا النظام بسهولة ، لذا البديل يكون باستخدام وتعريف SqlParameter:
C#:
كود PHP:
string sql string.Format("Select [First Name]+[Last Name] as [Full Name], Age From Employee where ID=@ID");
using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
// Fill params collection.
SqlParameter param = new SqlParameter();
param.ParameterName "@ID";
param.Value 10;
param.SqlDbType SqlDbType.Int;
cmd.Parameters.Add(param);
// تنفيذ جملة الاستعلام بأي شكل هنا
cmd.ExecuteNonQuery();

vb.net:
كود PHP:
Dim sql As String String.Format("Select [First Name]+[Last Name] as [Full Name], Age From Employee where 
كود PHP:
ID=@ID") 
Using cmd As New SqlCommand(sql, Me.sqlCn) 
    ' Fill params collection. 
    Dim param As New SqlParameter() 
    param.ParameterName = "
@ID
    param.Value = 10 
    param.SqlDbType = SqlDbType.Int 
    cmd.Parameters.Add(param) 
    
    ' تنفيذ جملة الاستعلام بأي شكل هنا 
    cmd.ExecuteNonQuery() 
End Using 
هنا كما لاحظت قمنا بتمرير باميترات إلى جملة استعلام قمنا نحن بكتابتها ضمن البرنامج .

- الحالة الثانية التي لدينا وهي الشائعة الاستخدام هي حالة تعريف Stored Procedure ، لو افترضنا مثلاً جملة الاستعلام التي أنشأناها في أول درس لنا بالشكل التالي :

كود PHP:
ALTER PROCEDURE dbo.GetAge
@condition int,
@
firstname char(10output
AS
SELECT @firstname=[First Namefrom Employee_info where age > @condition 
وقمنا بحفظها باسم GetAge ، الآن نريد استدعاءها من البرنامج ، يتم ذلك بالشكل التالي مثلاً :

C#:
كود PHP:
using (SqlCommand cmd = new SqlCommand("GetAge"cn))
{
cmd.CommandType CommandType.StoredProcedure;
SqlParameter param = new SqlParameter();
param.ParameterName "@condition";
param.SqlDbType SqlDbType.Int;
param.Value myAge;
param.Direction ParameterDirection.Input;
cmd.Parameters.Add(param);

param = new SqlParameter();
param.ParameterName "@firstnameName";
param.SqlDbType SqlDbType.Char;
param.Size 10;
param.Direction ParameterDirection.Output;
cmd.Parameters.Add(param);

cmd.ExecuteNonQuery();
MessageBox.Show(cmd.Parameters["@firstName"].Value.ToString());

vb.net:
كود PHP:
Using cmd As New SqlCommand("GetAge"cn
    
cmd.CommandType CommandType.StoredProcedure 
    
    Dim param 
As New SqlParameter() 
    
param.ParameterName "@condition" 
    
param.SqlDbType SqlDbType.Int 
    param
.Value myAge 
    param
.Direction ParameterDirection.Input 
    cmd
.Parameters.Add(param
    
    
    
    
param = New SqlParameter() 
    
param.ParameterName "@firstnameName" 
    
param.SqlDbType SqlDbType.[Char
    
param.Size 10 
    param
.Direction ParameterDirection.Output 
    cmd
.Parameters.Add(param
    
    
    
    
cmd.ExecuteNonQuery() 
    
MessageBox.Show(cmd.Parameters("@firstName").Value.ToString()) 
End Using 
كما لاحظت ، قمنا بتعريف نوع ال Command هنا نظراً لإن الافتراضي هو Text ، ومن ثم قمنا بتعريف متغير الدخول ومتغير الخروج أيضاً .

- التعامل مع DataReaders :

كما شاهدت في المثال السابق ، يمكن قراءة البيانات من DataReader بالشكل التالي مثلاً :
C#:
كود PHP:
string listItem "";
            while (
myDataReader.Read())
            {
                
listItem"Full Name: " myDataReader["Full Name"].ToString() + " Age: " myDataReader["Age"].ToString();
                
listBox1.Items.Add(listItem);
            } 
vb.net:
كود PHP:
Dim listItem As String "" 
While myDataReader.Read() 
    
listItem "Full Name: " myDataReader("Full Name").ToString() + " Age: " myDataReader("Age").ToString() 
    
listBox1.Items.Add(listItem
End While 
حيث تعود الدالة Read ب true ما دام هناك سجلات للقراءة ، وفي نفس الوقت مع كل استدعاء لها تنتقل إلى السجل التالي ...

طريقة القراءة تكون بتحديد الحقل المراد قراءته myDataReader["Age"] او بتحديد رقمه في الترتيب myDataReader[2] مثلاً .

الخاصية FieldCount تعطينا عدد النتائج المعادة ، لذا يمكننا تنفيذ نفس العملية السابقة بالشكل التالي :
c#:
كود PHP:
for (int i 0myDataReader.FieldCounti++)
{
                
listItem"Full Name: " myDataReader["Full Name"].ToString() + " Age: " myDataReader["Age"].ToString();
                
listBox1.Items.Add(listItem);

vb.net:
كود PHP:
For As Integer 0 To myDataReader.FieldCount 
    listItem 
"Full Name: " myDataReader("Full Name").ToString() + " Age: " myDataReader("Age").ToString() 
    
listBox1.Items.Add(listItem
Next 

NextResult :


تمكنك ال DataReader من تعريف جملتي استعلام لاعادة الناتج ، فمثلاً لاعادة اسماء الموظفين ثم اسماء المشاريع :
C#:
كود PHP:
string strSQL "Select * From Employee_info;Select * from projects";
SqlCommand myCommand = new SqlCommand(strSQLcn);
do
{
while (
myDataReader.Read())
{
for (
int i 0myDataReader.FieldCounti++)
 
listItem"Data: " myDataReader[0].ToString() ;
}
} while (
myDataReader.NextResult()); 
vb.net:
كود PHP:
Dim strSQL As String "Select * From Employee_info;Select * from projects" 
Dim myCommand As New SqlCommand(strSQLcn
Do 
    While 
myDataReader.Read() 
        For 
As Integer 0 To myDataReader.FieldCount 
            listItem 
"Data: " myDataReader(0).ToString() 
        
Next 
    End 
While 
Loop While myDataReader.NextResult() 

Data Access Layer :

في التطبيقات الجدية ، لا يتم وضع الكود مع المظهر مع سيناريو وعمليات البرنامج اضافة لطبقة البيانات، بل يتم فصل كل منها في طبقة منفصلة وهو ما يعرف باسم Layers ، لمعرفة المزيد عن هذا الموضوع يمكنك مراجعة الرابط التالي :
http://www.al-asiri.com/ShowRecord.a...b-87fd6082ff89
وهناك تطبيق ايضاً هنا :
http://vb4arab.com/vb/showthread.php...%E1%D8%C8%DE%C 7%CA

في هذه المرحلة ، سنحاول عمل data layer تكون خاصة بالتعامل مع قواعد البيانات لتحقيق نقطتين مهمتين :

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

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

يمكنك عمل هذه الطبقة بعدة طرق ، ابسطها استخدام بعض البرامج الجاهزة التي تقوم بهذه العملية وتقوم بعمل استخراج لهذه ال layer حسب لغة البرمجة التي تحددها ، ايضاً يوفر لك الدوت نت طريقة لهذه العملية ، الطريقة الثانية هي الطريقة اليدوية ...

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

1- عمليات فتح واغلاق قواعد البيانات :
C#:
كود PHP:
private SqlConnection cn = new SqlConnection();
public 
void OpenConnection(string connectionString)
{
cn.ConnectionString connectionString;
cn.Open();
}
public 
void CloseConnection()
{
cn.Close();

vb.net:
كود PHP:
Private cn As New SqlConnection() 
Public 
Sub OpenConnection(ByVal connectionString As String
    
cn.ConnectionString connectionString 
    cn
.Open() 
End Sub 
Public Sub CloseConnection() 
    
cn.Close() 
End Sub 
2- سيناريو عملية الحذف .
في هذه العملية سنتيح للمستخدم حذف الموظف باسمه ، او حذف الموظف برقمه ، او حذف الموظف مثلاً بدلالة العمر وبعدة اختيارات سواء اكبر او اقل او يساوي مثلاً مع استخدام مبدأ ال OverLoading ومبدأ عمل Enums ايضاً واللذان تم شرحهما في دروس سابقة .
*** لاحظ ان مهمتك في هذه المرحلة هي عمل كل الدوال التي يمكن استخدامها في البرنامج تحت اي ظرف من الظروف :
C#:
كود PHP:
public void DeleteEmployee(int id)
{
string sql string.Format("Delete from Employee where ID = {0}",
id);
using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
try
{
cmd.ExecuteNonQuery();
}
catch(
SqlException ex)
{
Exception error = new Exception("some error occures: "ex);
throw 
error;
}
}
}

public 
void DeleteEmployee(string name)
{
string sql string.Format("Delete from Employee where [First Name] = '{0}'",
name);
using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
try
{
cmd.ExecuteNonQuery();
}
catch(
SqlException ex)
{
Exception error = new Exception("some error occures: "ex);
throw 
error;
}
}
}

enum deletecondition
{
morethan=0,
lessthan=1,
equal=2
}
public 
void DeleteEmployee(int age,deletecondition delcondition)
{
string sql="";
if(
delcondition == deletecondition.morethan)
  
sql string.Format("Delete from Employee where age > {0}",age);
else if(
delcondition == deletecondition.lessthan)
 
sql string.Format("Delete from Employee where age < {0}",age);
else
 
sql string.Format("Delete from Employee where age = {0}",age);

using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
try
{
cmd.ExecuteNonQuery();
}
catch(
SqlException ex)
{
Exception error = new Exception("some error occures: "ex);
throw 
error;
}
}

vb.net:
كود PHP:
Public Sub DeleteEmployee(ByVal id As Integer
    
Dim sql As String String.Format("Delete from Employee where ID = '{0}'"id
    
Using cmd As New SqlCommand(sqlMe.sqlCn
        Try 
            
cmd.ExecuteNonQuery() 
        Catch 
ex As SqlException 
            Dim 
[error] As New Exception("some error occures: "ex
            Throw [
error
        
End Try 
    
End Using 
End Sub 
Public Sub DeleteEmployee(ByVal name As String
    
Dim sql As String String.Format("Delete from Employee where [First Name] = '{0}'"name
    
Using cmd As New SqlCommand(sqlMe.sqlCn
        Try 
            
cmd.ExecuteNonQuery() 
        Catch 
ex As SqlException 
            Dim 
[error] As New Exception("some error occures: "ex
            Throw [
error
        
End Try 
    
End Using
End Sub
enum deletecondition
{
morethan=0,
lessthan=1,
equal=2
}

Public 
Sub DeleteEmployee(ByVal age As IntegerByVal delcondition As deletecondition
    
Dim sql As String "" 
    
If delcondition deletecondition.morethan Then 
        sql 
String.Format("Delete from Employee where age > {0}"age
ElseIf 
delcondition deletecondition.lessthan Then 
        sql 
String.Format("Delete from Employee where age < {0}"age
    Else 
        
sql String.Format("Delete from Employee where age = {0}"age
    
End If 
    
    
    
Using cmd As New SqlCommand(sqlMe.sqlCn
        Try 
            
cmd.ExecuteNonQuery() 
        Catch 
ex As SqlException 
            Dim 
[error] As New Exception("some error occures: "ex
            Throw [
error
        
End Try 
    
End Using 
End Sub 

3- سيناريو عمليات الاضافة والتعديل :

بنفس الطريقة يمكن التعديل بعدة خيارات او الاضافة بعدة طرق .
بالنسبة لعملية الاضافة سنجبره على ادخال الاسم الأول والأخير فقط .
والتعديل ينبغي أيضاً أن يكون بنفس الصورة ، ولكن منعاً للاطالة سنعدل بدلالة الرقم الاسم الأول فقط .
C#:
كود PHP:
public void InsertEmployee(string fnamestring lname,  int age)
{
// Format and execute SQL statement.
string sql string.Format("Insert Into Employee_info" +
"([First Name], [Last Name]) Values" +
"('{0}', '{1}')",fnamelname);
using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
cmd.ExecuteNonQuery();
}
}

public 
void UpdateEmployee(int idstring newFirstName)
{
string sql =
string.Format("Update Employee Set [First Name] = '{0}' Where ID = '{1}'",
newFirstNameid);
using(SqlCommand cmd = new SqlCommand(sqlthis.sqlCn))
{
cmd.ExecuteNonQuery();
}

vb.net:
كود PHP:
Public Sub InsertEmployee(ByVal fname As StringByVal lname As StringByVal age As Integer
    
' Format and execute SQL statement. 
    Dim sql As String = String.Format("Insert Into Employee_info" + "([First Name], [Last Name]) Values" + "('
{0}', '{1}')", fname, lname) 
    
    Using cmd As New SqlCommand(sql, Me.sqlCn) 
        cmd.ExecuteNonQuery() 
    End Using 
End Sub 

Public Sub UpdateEmployee(ByVal id As Integer, ByVal newFirstName As String) 
    
    Dim sql As String = String.Format("Update Employee Set [First Name] = '
{0}' Where ID = '{1}'", newFirstName, id) 
    Using cmd As New SqlCommand(sql, Me.sqlCn) 
        cmd.ExecuteNonQuery() 
    End Using 
End Sub 

4- سيناريو عمليات البحث .

قبل البدء في سيناريو عملية البحث ، نود أن نشير إن الدوال السابقة ينقصها شيء هام وهي عملية ال Parameters لتلافي المشاكل الناتجة عن ال Sql Injection ، لكن كانت الامثلة السابقة للتوضيح فقط ، في عملية البحث الآن سنطبق ما تعلمناه لحل هذه المشكلة .
سنجرب عملية بحث واحدة عن الاسم الأول والأخير للأشخاص برقم ID معين ، لا تنسى أنك مطالب في Data Layer بعمل كل الطلبات التي قد يحتاجها مبرمج عمليات البرنامج لكي لا يحتاج لكتابة حتى جملة استعلام واحدة .

سنقوم اولاً بعمل Stored Procedure :

كود PHP:
CREATE PROCEDURE GetFirstNameByID
@id int,
@
fName char(10output
AS
SELECT @fName=[First Namefrom Employee_info where ID > @id 
ومن ثم نقوم نعرف الدالة الخاصة بعملية البحث بالشكل التالي :
C#:
كود PHP:
public string SelectName(int id)
{
using (SqlCommand cmd = new SqlCommand("GetFirstNameByID"cn))
{
cmd.CommandType CommandType.StoredProcedure;
SqlParameter param = new SqlParameter();
param.ParameterName "@id";
param.SqlDbType SqlDbType.Int;
param.Value ID;
param.Direction ParameterDirection.Input;
cmd.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName "@fName";
param.SqlDbType SqlDbType.Char;
param.Size 10;
param.Direction ParameterDirection.Output;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
return 
cmd.Parameters["@fName"].Value.ToString();
}
return 
carPetName;

vb.net:
كود PHP:
Public Sub InsertEmployee(ByVal fname As StringByVal lname As StringByVal age As Integer
    
' Format and execute SQL statement. 
    Dim sql As String = String.Format("Insert Into Employee_info" + "([First Name], [Last Name]) Values" + "('
{0}', '{1}')", fname, lname) 
    
    Using cmd As New SqlCommand(sql, Me.sqlCn) 
        cmd.ExecuteNonQuery() 
    End Using 
End Sub 

Public Sub UpdateEmployee(ByVal id As Integer, ByVal newFirstName As String) 
    
    Dim sql As String = String.Format("Update Employee Set [First Name] = '
{0}' Where ID = '{1}'", newFirstName, id) 
    Using cmd As New SqlCommand(sql, Me.sqlCn) 
        cmd.ExecuteNonQuery() 
    End Using 
End Sub 
--- لاحقاً يمكنك فصل ال DataLayer حتى في dll منفصلة لضمان تشغيلها مع اكثر من تطبيق ، في الاستخدام لاحقاً وعلى افتراض ان الفئة Class لطبقة البيانات DataLayer تحمل الاسم myDataLayer ، ولتطبيق عملية مثل الحذف كل المطلوب منك هو سطرين مثل الآتي :
C#:
كود PHP:
myDataLayer example=new myDataLayer();
example.OpenConnection(myconnectionstring);
example.DeleteEmployee(10);
example.DeleteEmployee("Ahmed"); 
vb.net:
كود PHP:
Dim example As New myDataLayer() 
example.OpenConnection(myconnectionstring
example.DeleteEmployee(10
example.DeleteEmployee("Ahmed"
وفقط !!!

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

Asynchronous Data Access :

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

C#:
كود PHP:
SqlConnection cn = new SqlConnection();
cn.ConnectionString =
@
"Data Source=(local)\SQLEXPRESS;Integrated Security=SSPI;" +
"Initial Catalog=AutoLot;Asynchronous Processing=true";
cn.Open(); 
vb.net:
كود PHP:
Dim cn As New SqlConnection() 
cn.ConnectionString "Data Source=(local)\SQLEXPRESS;Integrated Security=SSPI;" "Initial Catalog=AutoLot;Asynchronous Processing=true" 
cn.Open() 
أول خطوة قمنا بها هي تعريف الوضع Asynchronous Processing=true في ال ConnectioString بهذه الطريقة اصبحنا قادرين على الاستفادة من الدوال التالية :

BeginExecuteReader() و EndExecuteReader()
BeginExecuteNonQuery() و EndExecuteNonQuery()
BeginExecuteXmlReader() وEndExecuteXmlReader()

سنجرب الآن على BeginExecuteReader و EndExecuteReader ، وسنبدأ بتأخير جملة الاستعلام الأولى لخمس ثوان مثلاً :
c#:
كود PHP:
string strSQL "WaitFor Delay '00:00:05';Select * From Employee_info";
SqlCommand myCommand = new SqlCommand(strSQLcn); 
vb.net:
كود PHP:
Dim strSQL As String "WaitFor Delay '00:00:05';Select * From Employee_info" 
Dim myCommand As New SqlCommand(strSQLcn
هنا سنقوم بتنفيذ عمليات أخرى على ثريد آخر :
c#:
كود PHP:
IAsyncResult itfAsynch;
itfAsynch myCommand.BeginExecuteReader(CommandBehavior.CloseConnection 
);
vb.net:
كود PHP:
Dim itfAsynch As IAsyncResult 
itfAsynch 
myCommand.BeginExecuteReader(CommandBehavior.CloseConnection
وتنفيذ بعض العمليات حتى الانتهاء من تنفيذ الثريد
C#:
كود PHP:
while (!itfAsynch.IsCompleted)
{
// تغيير قيمة مؤشر مثلاً .
Thread.Sleep(1000);

vb.net:
كود PHP:
While Not itfAsynch.IsCompleted 
    
' تغيير قيمة مؤشر مثلاً . 
    Thread.Sleep(1000) 
End While 
الآن بما أننا خرجنا من ال Loop السابقة فهذا يعني انتهاء التنفيذ الأول ، الآن سنقوم بتنفيذ العملية التي نريدها .
C#:
كود PHP:
SqlDataReader myDataReader myCommand.EndExecuteReader(itfAsynch);
while (
myDataReader.Read())
{
MessageBox.Show(myDataReader[1].ToString());
}
myDataReader.Close(); 
vb.net:
كود PHP:
Dim myDataReader As SqlDataReader myCommand.EndExecuteReader(itfAsynch
While 
myDataReader.Read() 
    
MessageBox.Show(myDataReader(0).ToString()) 
End While 
myDataReader.Close() 
فقط !
تبقى نقطة واحدة قبل انهاء وضع ال Connected وهي نقطة ال Transactions ، وهي ما سنتحدث عنه لاحقاً .

Transactions :

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

لذا خطوات العمل في قواعد البيانات لا بد أن تكون بالشكل التالي :
- سحب 500 دولار من حساب عميل 1 .
- ايداع 500 دولار في حساب عميل 2 .

وهاتان العمليتان لابد ان تتم سوية ، بمعنى لو تمت العملية الأولى ولم تتم العملية الثانية لانقطاع الاتصال مثلاً فهذا غير مقبول ، لذا لا بد ان يتم اعتماد العمليتين أو حذف اي عملية منهم تتم دون الأخرى وهو ما يعرف باسم roll back .

إذا قمنا بعمل transaction سيتم تعريف هذه المجموعة من العمليات في نظام قاعدة البيانات DBMS على شكل وحدة واحدة بحيث يتم تنفيذها سوية او عدم تنفيذها سوية .
الفئة المسؤولة عن هذه العملية لدينا هي الفئة SqlTransaction الموجودة ضمن مجال الأسماء System.Data.SqlClient ، هناك فئات أخرى يمكنها تطبيق هذه العملية ضمن مجال أسماء .net ايضاً مثل :

System.EnterpriseServices : تتيح لنا هذه الفئة الاتصال مع مكونات COM+ التي تقدم لنا الدعم في هذه العملية .
System.Transactions : تتيح لنا هذه الفئة بناء تطبيقات تدعم ال transactions .
WCF و WWF : تمكننا هاتان الفئتان من تطبيق مبادئ ال transaction ايضاً .

حتى في نظم قواعد البيانات يمكنك القيام بهذه المهمة عن طريق تعريف Stored Procedure يقوم بعمل transactions عن طريق TRANSACTIONو ROLLBACKو COMMIT ، يمكنك البدء في هذا النوع من هنا :
http://msdn.microsoft.com/en-us/library/ms187844.aspx

في ADO.net لدينا الفئة DBTransaction التي تطبق الواجهة IDbTransaction interface والذي يحتوي على الدوال الرئيسية التالية :
C#:
كود PHP:
public interface IDbTransaction IDisposable
{
IDbConnection Connection get; }
IsolationLevel IsolationLevel get; }
void Commit();
void Rollback();

vb.net:
كود PHP:
Public Interface IDbTransaction 
    Inherits IDisposable 
    ReadOnly Property Connection
() As IDbConnection 
    ReadOnly Property IsolationLevel
() As IsolationLevel 
    Sub Commit
() 
    
Sub Rollback() 
End Interface 
يضيف لنا ال SqlTransaction دالة جديدة هي Save والتي تتيح لنا حفظ نقطة يتم الرجوع إليها في حالة الفشل في اتمام العملية بدل الرجوع في العملية بالكامل - لو كان هناك اجزاء من العملية أو العملية على مراحل - .
ابسط مثال على تطبيق هذه العملية ، هو افتراض وجود جدول يحتوي على ( اسم العميل - المبلغ المودع ) وعندما نقوم بعملية تحويل من حساب إلى آخر نقوم بعملية بالشكل التالي :
C#:
كود PHP:
SqlCommand cmdGet = new SqlCommand("update customers set total=total-" totalmoney.ToString() + " where ID" custID.ToString(), cn);
cmdSelect.ExecuteNonQuery();
SqlCommand cmdSet = new SqlCommand("update customers set total=total+" totalmoney.ToString() + " where ID" SuppID.ToString(), cn);
cmdSelect.ExecuteNonQuery(); 
vb.net:
كود PHP:
Dim cmdGet As New SqlCommand("update customers set total=total-" totalmoney.ToString() + " where ID" custID.ToString(), cn
cmdSelect.ExecuteNonQuery() 
    
Dim cmdSet As New SqlCommand("update customers set total=total+" totalmoney.ToString() + " where ID" SuppID.ToString(), cn
cmdSelect.ExecuteNonQuery() 
في هذه العملية ولأي سبب كان قد يتوقف الجزء الثاني من العملية ، لذا سنحاول اخبار نظام قاعدة البيانات بأننا سننفذ كلا العمليتين في نفس الوقت ، ولو لم يتم تنفيذ واحدة منهما سيتم الغاء الأخرى مباشرة .
C#:
كود PHP:
SqlCommand cmdGet = new SqlCommand("update customers set total=total-" totalmoney.ToString() + " where ID" custID.ToString(), cn);
SqlCommand cmdSet = new SqlCommand("update customers set total=total+" totalmoney.ToString() + " where ID" SuppID.ToString(), cn);
SqlTransaction sqltr null;
try
{
sqltr sqlCn.BeginTransaction();
cmdGet.Transaction sqltr;
cmdSet.Transaction sqltr;
cmdGet.ExecuteNonQuery();
cmdSet.ExecuteNonQuery();
if (
throwEx)
{
throw new 
ApplicationException("all operation canceld, some errors occures");
}
sqltr.Commit();
}
catch (
Exception ex)
{
MessageBox.Show(ex.Message);
tx.Rollback();
}

vb.net:
كود PHP:
Dim cmdGet As New SqlCommand("update customers set total=total-" totalmoney.ToString() + " where ID" custID.ToString(), cn
Dim cmdSet As New SqlCommand("update customers set total=total+" totalmoney.ToString() + " where ID" SuppID.ToString(), cn
Dim sqltr As SqlTransaction Nothing 
Try 
    
sqltr sqlCn.BeginTransaction() 
    
    
cmdGet.Transaction sqltr 
    cmdSet
.Transaction sqltr 
    
    cmdGet
.ExecuteNonQuery() 
    
cmdSet.ExecuteNonQuery() 
    
    If 
throwEx Then 
        
Throw New ApplicationException("all operation canceld, some errors occures"
    
End If 
    
    
sqltr.Commit() 
Catch 
ex As Exception 
    MessageBox
.Show(ex.Message
    
tx.Rollback() 
End Try 
كما لاحظت ، نقوم ببدء عملية ال transaction ، وما لم يحدث أي خطأ فلن ندخل في الشرط ولذا سيتم تنفيذ دالة Commit لتنفيذ العمليتين واعتمادهما ، أما في حالة حدوث اي خطأ فسنقوم برمي throw Exception والذي ينقلنا مباشرة إلى Catch لنقوم هناك باستدعاء الدالة rollback من اجل الغاء جميع التأثيرات التي حدثت .

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

لو جربت مثالك الآن ستجد ان قيمة مبلغ العميل 1 مثلاً لم تتأثر ، أما في حالة عدم وجود خطأ في الجملة الثانية فستجد ان الكمية المحددة من المبلغ قد تم نقلها من عميل 1 إلى عميل 2 .
*** طبعاً في تطبيقاتك الجدية لن يكون نظام الايداع والصرف بهذا الشكل ، بل في العادة سيكون هناك جدول او اكثر من جدول يحتوي على العمليات المجراه لكل عميل من ايداع وصرف وسحب وخلافه .

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

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


توقيع : khaledbelal



(أَفَأَمِنَ أَهْلُ الْقُرَى أَن يَأْتِيَهُمْ بَأْسُنَا بَيَاتاً وَهُمْ نَآئِمُونَ {97} أَوَ أَمِنَ أَهْلُ الْقُرَى أَن يَأْتِيَهُمْ بَأْسُنَا ضُحًى وَهُمْ يَلْعَبُونَ {98}
أَفَأَمِنُواْ مَكْرَ اللّهِ فَلاَ يَأْمَنُ مَكْرَ اللّهِ إِلاَّ الْقَوْمُ الْخَاسِرُونَ {99}).
سورة الأعراف.

رد مع اقتباس
إضافة رد


تعليمات المشاركة
لا تستطيع إضافة مواضيع جديدة
لا تستطيع الرد على المواضيع
لا تستطيع إرفاق ملفات
لا تستطيع تعديل مشاركاتك

BB code is متاحة
كود [IMG] متاحة
كود HTML معطلة

الانتقال السريع

المواضيع المتشابهه
الموضوع كاتب الموضوع المنتدى مشاركات آخر مشاركة
الدرس الحادي والخمسون : System.IO - الجزء الثالث والأخير - دورة .net 2008 khaledbelal دورة .NET 2008 من منتدى فيجوال بيسك للعرب 0 03-01-2010 01:52 PM
الدرس الثالث والأربعون : Operator Overloading دورة .net 2008 khaledbelal دورة .NET 2008 من منتدى فيجوال بيسك للعرب 0 02-26-2010 04:22 PM
الدرس الثالث والثلاثون : ال Events دورة .net 2008 khaledbelal دورة .NET 2008 من منتدى فيجوال بيسك للعرب 0 02-25-2010 02:40 PM
الدرس الثالث والعشرون : ال Abstract دورة .net 2008 khaledbelal دورة .NET 2008 من منتدى فيجوال بيسك للعرب 0 02-22-2010 01:57 PM
الدرس الثالث عشر : مقدمة إلى الفئات Classes دورة .net 2008 khaledbelal دورة .NET 2008 من منتدى فيجوال بيسك للعرب 0 02-19-2010 07:56 PM

استضافة الحياة

الساعة الآن 02:47 AM.


Powered by vBulletin® v3.8.4, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. , TranZ By Almuhajir
النسخة الفضية
Ads Management Version 3.0.1 by Saeed Al-Atwi

SlamDesignzslamDesignzEdited by Riad Al-Ganah Team - جميع الحقوق محفوظة لشبكة رياض الجنة

Privacy Policy Valid XHTML 1.0 Transitional By SlamDesignz Valid CSS Transitional By SlamDesignz