کلاس Connection

هر data provider در ADO.Net شامل یک کلاس connection است که از کلاس system.data.common.DbConnection ارث بری می‌کند. برای همه کلاسهای connection مربوط به data provider های مختلف DbConnection به عنوان کلاس پایه به حساب می‌آید. جدول زیر کلاس‌های connection برای هر data provider را نشان می‌دهد.

Connection class Data provider
sqlConnection SQL Server
OleDbConnection OLE DB
OdbcConnection ODBC

کلاس DbConnection رابط IDbConnection را پیاده سازی می‌کند که، دارای متدها و خصوصیاتی (properties) برای تعریف یک connection (ارتباط) یا باز کردن یک connection به یک منبع داده می‌باشد. باز کردن یک connection باعث اشغال حافظه کامپیوتر می‌شود، مثلاً ممکن است برای انتقال اطلاعات از بافر کارت شبکه استفاده کند، هم چنین بدیهی است که برای استفاده از آن سایر سخت افزارها مثل RAM و CPU درگیر هستند، بنابراین بعد از این که استفاده ما از Connection تمام شد باید آن را ببندیم. برای وصل شدن به یک دیتابیس ما باید آدرس و تنظیمات و سایر چیزهای لازم برای وصل شدن به دیتابیس مثل آدرس آن را به برنامه بدهیم، رشته اتصال (Connection String) برای ما این کار را انجام می‌دهد. در زیر متدها و خصوصیات رابط IDbConnection که در همه کلاس‌های Connection وجود دارند را ذکر کرده‌ایم :

خاصیت توضیح
ConnectionString رشته‌ای است، که از آن، برای برقراری ارتباط با بانک اطلاعاتی استفاده می‌شود.
ConnectionTimeout مدت زمانی که باید منتظر برقراری ارتباط با بانک بود را، مشخص می‌کند.
Database نام بانک اطلاعاتی که قرار است ارتباط با آن برقرار شود را، مشخص می‌کند.
State وضعیت فعلی ارتباط را مشخص می‌کند.

 

متد توضیح
()BeginTransaction تراکنش با بانک را شروع می‌کند.
()ChangeDatabase ارتباط را از یک دیتابیس به دیتابیس دیگر تغییر می‌دهد.
()Close ارتباط با دیتابیس را قطع می‌کند.
()CreateCommand یک شیء SqlCommand از روی دستور SQL تعیین شده ایجاد می‌کند.
()Open ارتباط با بانک را برقرار می‌کند.

باید به این نکته اشاره کرد که هر کدام از کلاس‌های connection مربوط به هر data provider می‌تواند بیشتر از این دو جدول متد و property داشته باشد، ولی در این صورت برای خود آن کلاس یکتاست، که ما در این جدول‌ها ذکر نکردیم. برای مثال‌های این مقاله ما از SQL Sever به عنوان data provider استفاده می‌کنیم. بنابراین ما از کلاس SqlConnection به عنوان کلاس connection ای برای ارتباط با SQL Server که یک data provider است، استفاده می‌کنیم. برای ساختن یک شیء از این کلاس، از خط کد زیر استفاده می‌کنیم (در اینجا ما از یک سازنده که هیچ پارامتری نمی‌گیرد استفاده کردیم):

SqlConnection connection = new SqlConnection();

حالا برای این که این شیء بداند که باید به کدام دیتابیس و چه نوع دیتابیسی وصل شود باید connection string را مشخص کنیم. این شیء connection ی که ساخته‌ایم یک خاصیت به اسم connectionString دارد که می‌توان با استفاده از آن این کار را انجام دهیم. در خط زیر به برنامه می گوییم:

connection.ConnectionString = @"Data Source=.SQLEXPRESS;Initial Catalog=University;" +
                               "Integrated Security=SSPI";

به جای این دو خط کد می‌توانیم در هنگام ساختن شئ connection string را هم مستقیماً به آن بدهیم (به این حالت کلاس که پارامتر هم می‌گیرد overloaded constructor یا سربارگذاری سازنده می گویند).

SqlConnection connection = new SqlConnection(@"Data Source=.SQLEXPRESS;" +
                       "Initial Catalog=University;Integrated Security=SSPI");

این connection string می‌گوید که از دیتابیس university استفاده کن. فقط وقتی که connection بسته است (ارتباط با بانک قطع است)، می‌توان connection string را مقداردهی کرد یا تغییر داد. کلاس connection به ما این امکان را هم می‌دهد که به قسمت‌های مختلف connection string هم دسترسی داشته باشیم. این کار را با استفاده از خاصیت‌های آن می‌توانیم انجام دهیم. یک خاصیت به اسم Database داریم که به برنامه می‌گوید که از کدام دیتابیس استفاده کند. این خاصیت در connection string با نام Initial Catalog مشخص شده است. با استفاده از کلاس connection و متد ChangeDatabase می‌توان دیتابیس مورد استفاده در برنامه را تغییر داد (البته همان طور که گفتیم connection باید بسته باشد).

connection.ChangeDatabase("AnotherDatabase");

این خط کد، دیتابیس مورد استفاده را از University به AnotherDatabase یا دیتابیسی دیگر عوض می‌کند.
یک خاصیت دیگر به نام connectionTimeout داریم که مدت زمانی که connection باز است را به ما می‌گوید که اگر آن را مقدار دهی نکرده‌اید به صورت پیشفرض مقدار 15 برای آن مقداردهی می‌شود. بعد از این زمان یک استثناء (exception) رخ می‌دهد که زمان تمام شده است. برای باز کردن یک connection ما از متد ()open استفاده می‌کنیم. قبل از صدا زدن این متد باید connection string را مقداردهی کرده باشیم. بعد از این که از این connection استفاده کردیم آن را باید حتماً ببندیم که این کار را هم با متد ()close انجام می‌دهیم. وقتی که از using استفاده می‌کنیم بلافاصله که کار ما تمام شد به صورت اتوماتیک connection بسته می‌شود.

using (SqlConnection connection = new SqlConnection())
{
   // some code....
   connection.Open();
   // some code....
}

ما تعریف و مقداردهی را در داخل پرانتز using قرار می‌دهیم این به ما می‌گوید که connection ای که در داخل پرانتز مربوط به using قرار دارد فقط در داخل بلاک آن وجود دارد و قابل استفاده است. بعد از این که بلاک تمام شد connection بسته خواهد شد. اگر شما از متد ()close استفاده می‌کنید باید مطمئن شوید که آن را در قسمت finaly قرار می‌دهید.

try
{
   connection.Open();
}
catch(SqlException)
{
}
finally
{
   connection.Close();
}

این کار برای این است که اگر ما آن را در بلاک try قرار دهیم و یک exception رخ دهد در این صورت آن کد اجرا نمی‌شود و در نتیجه connection باز می‌ماند ولی در این حالت حتی با وجود رخداد exception هم بلاک finaly اجرا می‌شود و به مشکلی بر نمی‌خوریم. با استفاده از خاصیتی به نام state که مربوط به connection است می‌توان از وضعیت connection با خبر شد که آیا باز است یا بسته.State مقدار خود را از system.data.connectionStateEnumeration می‌گیرد. در جدول زیر مقادیر نوع شمارشی ConnectionState ذکر شده است :

مقدار توضیح
Broken مشخص می‌کند که ارتباط با بانک با شکست مواجه شده است.
Closed مشخص می‌کند که ارتباط بسته است.
Connecting مشخص می‌کند که ارتباط با منبع داده برقرار است.
Executing مشخص می‌کند که ارتباط در حال اجرای یک دستور است.
Fetching مشخص می‌کند که ارتباط در حال دریافت داده است.
Open مشخص می‌کند که ارتباط باز است.

کلاس Connection دو رویداد (event) هم در اختیار شما قرار می‌دهد، که شما می‌توانید از آنها استفاده کنید. اولی InfoMessage است که از آن می‌توان برای گرفتن پیام‌های اطلاعاتی استفاده کرد. و هر وقت که وضعیت مربوط به connection عوض شود رویداد StateChange رخ می‌دهد (trigger می‌شود).

static void con_StateChange(object sender, System.Data.StateChangeEventArgs e)
{
    Console.WriteLine("State has been changed from {0} to {1}.",
            e.OriginalState.ToString(), e.CurrentState.ToString());
}

static void Main()
{
    SqlConnection con = new SqlConnection();
    con.ConnectionString = @"Data Source=.SQLEXPRESS;Initial Catalog=Northwind;" + 
                            "Integrated Security=SSPI";
    con.StateChange += new System.Data.StateChangeEventHandler(con_StateChange);
    con.Open(); // Opens a connection
    con.Close(); // Closes a connection
}
State has been changed from Closed to Open.
State has been changed from Open to Closed.

Con_StateChange را برای کنترل کردن رویداد عوض شدن وضعیت داریم و این تابع را به رویداد کانکشن (StateChange) انتساب می‌دهیم تا هر وقت وضعیت کانکشن عوض شد از این استفاده کند و کارهای کنترلی را انجام دهد که در اینجا ما به خاطر آموزش فقط یک جمله پرینت می‌کنیم. وقتی که ما متد ()open را صدا می‌زنیم وضعیت کانکشن از close به open تغییر می‌کند و کنترل کننده رویداد (event handler) را صدا می زند و خط اول را چاپ می‌کند و وقتی که متد ()close را صدا می‌زنیم همین اتفاق می افتد و خط دوم را چاپ می‌کند.