همراهان گرامی سلام، عرض ادب خدمت شما ، امیدوارم که شاد باشید.دراین بخش چگونگی کار با داده ی غیر متصل با استفاده از آبجکت های DataSet و SqlDataAdapter را توضیح می دهد. در اینجا اهداف این بخش بیان می شوند:

· درک نیاز به داده ی غیرمتصل.

· برقراری یک درک پایه از آنچه دیتاست مربوط به آن می شود.

· فراگیری استفاده از یک SqlDataAdapter برای بازیابی و آپدیت کردن داده.

مقدمه:

در درس ۳، در مورد یک حالت اتصال کامل از عملکرد برای ارتباط با یک منبع داده با استفاده از آبجکت SqlCommand بحث کردیم. در درس ۴ در مورد چگونگی خواندن سریع داده و برقراری اتصال با SqlDataReader بحث کردیم. این درس نشان می دهد که با استفاده از آبجکت های DataSet و SqlDataAdapter بین اثر متقابل SqlConnection و SqlDataReader چگونه چیزی را منتشر کنیم.

یک DataSet یک داده ی ذخیره شده در حافظه می باشد که می تواند جدول های بسیاری در خود داشته باشد. DataSet ها فقط داده را در خود دارند و با منبع داده تعاملی ندارند. این SqlDataAdapter است که اتصالات با منبع داده را سازماندهی می کند و به ما رفتار disconnected می دهد. SqlDataAdapter تنها زمانی یک اتصال را باز می کند که لازم باشد و به محض اینکه عملکرد مربوط به خود را اجرا کرد، آن را می بندد. به عنوان مثال SqlDataAdapter در هنگام پر کردن یک DataSet با داده، عملکردهای زیر را اجرا می کند:

۱٫ باز کردن اتصال.

۲٫ بازیابی داده به دیتاست

۳٫ بستن اتصال.

و در هنگام آپدیت کردن منبع داده با تغییرات DataSet فعالیت های زیر را انجام می دهد:

۱٫ باز کردن اتصال.

۲٫ نوشتن تغییرات از DataSet به منبع داده.

۳٫ بستن اتصال.

بین عملکردهای Fill و Update اتصالات منبع داده بسته شده و شما برای خواندن و نوشتن داده با DataSet طوری که نیاز دارید، آزاد می باشید. اینها مکانیک های کار کردن با داده ی غیرمتصل می باشد. از آنجایی که برنامه ها فقط در هنگام نیاز به اتصالات متوسل می شوند، برنامه مقیاس پذیرتر می شود.

دو سناریو وجود دارند که علت کار کردن شما با داده ی غیرمتصل را توضیح می دهند: افرادی که بدون اتصال شبکه کار می کنند و وب سایت ها را مقیاس پذیرتر ( scalable) می سازند. فروشنده هایی را در نظر بگیرید که در هنگام سفر نیاز به مشتری دارند. در ابتدای روز لازم است برای در دسترس داشتن آخرین اطلاعات موجود با دیتابیس اصلی همگام باشند. در طول روز اصلاحاتی را بر روی داده ی مشتری موجود انجام داده، مشتری های جدید اضافه می کنند و ترتیب های جدید وارد می کنند. این مسئله خوب می باشد، زیرا دارای یک منطقه یا مشتری ارائه شده هستند که در آن افراد دیگر همان رکوردها را تغییر نخواهند داد. در انتهای روز فروشنده ها به شبکه متصل خواهند شد و تغییرات را آپدیت خواهند کرد.

سناریوی دیگر ساخت یک وب سایت مقیاس پذیرتر (scalabe) می باشد. با یک SqlDataReader، مجبور هستید هر زمان که یک صفحه را نمایش می دهید برای رکوردها به دیتابیس بازگردید. این مسئله برای بارگذاری هر صفحه به یک اتصال جدید نیاز دارد که با افزایش تعداد یوزرها به مقیاس پذیری صدمه خواهد زد. یک روش برای خلاص شدن از این موضوع استفاده از DataSet یک می باشد که یک بار آپدیت شده و در حافظه ی پنهان ذخیره سازی شده است. هر تقاضایی برای صفحه حافظه ی پنهان را چک کرده و اگر در آن داده ای موجود نباشد، داده بارگذاری می کند و یا اینکه فقط داده را از حافظه ی پنهان بیرون کشیده و آن را نمایش می دهد.

استثنائات مربوط به سناریوی بالا شامل موقعیت هایی است که در آن لازم است داده را آپدیت کنید و سپس بر اساس طبیعت چگونگی استفاده از استراتژی خود، باید تصمیم بگیرید. اگر اطلاعات شما در درجه ی اول فقط خوانده می شوند از داده ی غیرمتصل استفاده کنید، اما وقتی که ملزومات یک مورد دینامیک تر فرا می خوانند، به انتخاب های دیگر نیز دقت داشته باشید ( به عنوان مثال استفاده از آبجکت SqlCommand برای آپدیت شدن سریع). همچنین اگر مقدار داده آنقدر زیاد باشد که نگهداری آن در حافظه غیرعملی می نماید، برای خواندن داده به SqlDataReader نیاز خواهید داشت. یک نفر ممکن است با استثنائات زیادی مواجه شود، اما نیروی راهنمای درست باید از ملزومات برنامه ی شما باشد که بر روی طراحی شما نیز تاثیر خواهد داشت.

ایجاد آبجکت DataSet:

هیچ چیز خاصی در مورد نمونه گذاری یک DataSet وجود ندارد. شما فقط یک نمونه ی جدید ایجاد کرده اید، درست مانند هر آبجکت دیگری:

DataSet dsCustomers = new DataSet();

سازنده ی دیتاست نیازی به پارامتر ندارد. به هرحال یک بارگذاری وجود دارد که یک رشته را برای نام دیتاست می پذیرد که مجبور به مرتب کردن داده به XML باشید، استفاده می شود. از آنجایی که این مورد برای این مثال لازم نیست، آن را رها می کنم. اکنون DataSet خالی می باشد و به یک SqlDataAdapter برای بارگذاری آن نیاز دارید.

ایجاد یک SqlDataAdapter:

SqlDataAdapter دستورت SQL و آبجکت اتصال را برای خواندن و نوشتن داده حفظ می کند. شما آن را با یک عبارت SQL select و آبجکت اتصال آغاز می کنید:

SqlDataAdapter daCustomers = new SqlDataAdapter(

‎ “select CustomerID, CompanyName from Customers”, conn);‎

کد بالا یک SqlDataAdapter, daCustomers جدید ایجاد می کند. عبارت SQL select مشخص می کند که چه داده ای در یک DataSet خوانده خواهد شد. آبجکت اتصال ، conn، تقریبا باید نمونه گذاری شده باشد اما باز نشده باشد. باز کردن و بستن اتصال در طی فراخوانی های متود های Update و Fill از مسئولیت های SqlDataAdapter می باشد.

همانطور که قبلا نشان داده شد، SqlDataAdapter حاوی همه ی دستورات لازم برای تعامل با منبع داده می باشد. کد نشان می دهد که چگونه وضعیت انتخاب را تعیین کنید، اما عبارت insert، update و delete را نشان نداد. اینها پس از نمونه گذاری به SqlDataAdapter اضافه می شوند.

دو راه برای افزودن فرمان های insert, update و delete وجوو دارد: از طرق پراپرتی های SqlDataAdapter یا با استفاده از یک SqlCommandBuilder. در این درس تصمیم دارم راه ساده ی انجام آن را با SqlCommandBuilder نشان دهم. در درس بعدی چگونگی استفاده از پراپرتی های SqlDataAdapter راتوضیح خواهم داد که کار بیشتری می برد اما قابلیت های بیشتری از SqlCommandBuilder به شما ارائه می دهد. در اینجا چگونگی افزودن دستورات به یک SqlDataAdapter با یک SqlCommandBuilder را مشاهده می کنید:

SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daCustomers);‎

به کد بالا دقت داشته باشید که SqlCommandBuilder با یک پارامتر سازنده ی مجزا از نمونه ی SqlDataAdapter,daCustomers, نمونه گذاری شده است. این به SqlCommandBuilder می گوید که SqlDataAdapter چه دستوراتی می افزاید. SqlCommandBuilder عبارت انتخاب SQL را خواهد خواند و به فرمان های insert، update و delete اشاره می کند و به پراپرتی های Insert, Update, و Delete از SqlDataAdapter فرمان های جدیدی اختصاص می دهد.

همانطور که قبلا ذکر کردم، SqlCommandBuilder دارای محدودیت هایی می باشد. و وقتی کار میکند که یک عبارت select ساده روی یک جدول مجزا را انجام می دهید. به هرحال وقتی که نیاز به اتصال دو یا چند جدول دارید و یا باید یک پروسه ی ذخیره سازی انجام دهید، کار نحواهد کرد. برای کار کردن با آن در درس های بعدی توضیحاتی ارائه خواهم داد.

پر کردن DataSet:

زمانیکه نمونه های DataSet و SqlDataAdapter دارید، لازم است که DataSet را پر کنید. در اینجا چگونگی انجام آن را با استفاده از متود Fill از SqlDataAdapter مشاهده می کنید.

daCustomers.Fill(dsCustomers, “Customers”);

متود Fill در کد بالا دو پارامتر می گیرد: یک DataSet و نام جدول. DataSet باید قبل از اینکه سعی کنیم آن را با داده پر کنیم، نمونه گذاری شده باشد. پارامتر دوم نام جدول می باشد که در DataSet ایجاد خواهد شد. شما می توانید هر نامی که می خواهید به جدول بدهید. هدف این است که بعدها بتوانید جدول را با یک نام معنادار تشخیص دهید. معمولا من همان نام جدول دیتابیس را خواهم داد. به هرحال اگر فرمان انتخاب SqlDataAdapter حاوی یک اتصال است، لازم است نام معنادار دیگری انتخاب کنید.

متود Fill دارای یک overload میباشد که فقط برای DataSet یک پارامتر را می پذیرد. در این مورد جدول ایجاد شده دارای نام پیش فرض “table1” می باشد. عدد برای هر جدول اضافه شده به DataSet یک عدد رو به افزایش خواهد بود (table2, table3, …, tableN) که نام جدول در متود Fill تعیین نشد.

استفاده از DataSet:

یک DataSet هم با ASP.NET و هم با Windows فرم های DataGrids محدود خواهد شد. در اینجا مثالی را مشاهده می کنید که DataSet را به یک Windows طرح های DataGrid اختصاص داده است:

dgCustomers.DataSource = dsCustomers;
dgCustomers.DataMember = “Customers”;

اولین کاری که در کد بالا انجام می دهیم اختصاص داده DataSet به پراپرتی DataSource از DataGrid می باشد. این امر به DataGrid اجازه می دهد تا بداند که چیزی برای اتصال به آن وجود دارد، اما شما یک علامت + در GUI دریافت خواهید کرد، زیرا DataSet می تواند چند جدول را حفظ کند و این به مشا اجازه خواهد داد تا هر جدول موجود را باز کنید. برای تعیین دقیق اینکه کدام جدول استفاده شود، پراپرتی DataGrid’s DataMember را به نام جدول تنظیم کنید. در مثال نام Customers را تنظیم کردیم که همان نامی می باشد که به عنوان پارامتر دوم برای متود SqlDataAdapter Fill استفاده شد. به این دلیل است که تمایل دارم در متود Fill به جدول نام دهم، چرا که کد بعدی را خواناتر می سازد.

آپدیت کردن تغییرات:

پس از اینکه تغییراتی بر روی داده اعمال شده است، تمایل خواهید داشت که تغییرات را در پشت دیتابیس بنویسید. به بحث قبل در قسمت مقدمه ی این مقاله در مورد راهنمایی آپدیت کردن، مراجعه کنید. کد زیر چگونگی استفاده از متود Update را برای SqlDataAdapter برای فرستادن تغییرات به پشت دیتابیس نشان می دهد.

daCustomers.Update(dsCustomers, “Customers”);

متود Update در بالا روی نمونه ی SqlDataAdapter فراخوانده می شود که dsCustomers DataSet را پر می کند. پارامتر دوم از متود Update جدولی از DataSet را که باید آپدیت شود مشخص می کند. جدول حاوی لیستی از رکوردها می شود که تغییر یافته اند، و پراپرتی های Insert, Update و Delete از SqlDataAdapter حاوی عبارت SQL می باشد که برای ساخت اصلاحات دیتابیس استفاده می شود.
Putting it All Together

تاکنون بخش های لازم برای اجرای سازماندهی داده ی غیرمتصل را مشاهده کردید. آنچه شما واقعا نیاز دارید، مشاهده ی همه ی این اجراها در یک برنامه است. Listing 1 نشان می دهد که چگونه کد از تمام بخش های قبل در یک برنامه ی در حال کار استفاده می شود که برای برقراری نکان این درس ساده شده است.

using System;‎

using System.Data;‎

using System.Data.SqlClient;‎

using System.Drawing;‎

using System.Windows.Forms;‎

class DisconnectedDataform : Form

‎{‎

private SqlConnection conn;‎

private SqlDataAdapter daCustomers;‎

private DataSet dsCustomers;‎

private DataGrid dgCustomers;‎

private const string tableName = “Customers”;‎

‎// initialize form with DataGrid and Button‎

public DisconnectedDataform()‎

‎{‎

‎// fill dataset‎

Initdata();‎

‎// set up datagrid‎

dgCustomers = new DataGrid();‎

dgCustomers.Location = new Point(5, 5);‎

dgCustomers.Size = new Size(‎

‎ this.ClientRectangle.Size.Width – 10,‎

‎ this.ClientRectangle.Height – 50);‎

dgCustomers.DataSource = dsCustomers;‎

dgCustomers.DataMember = tableName;‎

‎// create update button‎

Button btnUpdate = new Button();‎

btnUpdate.Text = “Update”;‎

btnUpdate.Location = new Point(‎

this.ClientRectangle.Width/2 – btnUpdate.Width/2,‎

this.ClientRectangle.Height – (btnUpdate.Height + 10));‎

btnUpdate.Click += new EventHandler(btnUpdateClicked);‎

‎// make sure controls appear on form‎

Controls.AddRange(new Control[] { dgCustomers, btnUpdate });‎

‎}‎

‎// set up ADO.NET objects‎

public void Initdata()‎

‎{‎

‎// instantiate the connection‎

conn = new SqlConnection(

‎”Server=(local);DataBase=Northwind;Integrated ‎Security=SSPI”);‎

‎// ۱٫ instantiate a new DataSet‎

dsCustomers = new DataSet();‎

‎// ۲٫ init SqlDataAdapter with select command and connection

daCustomers = new SqlDataAdapter(

‎”select CustomerID, CompanyName from Customers”, conn);‎

‎// ۳٫ fill in insert, update, and delete commands‎

SqlCommandBuilder cmdBldr = new ‎SqlCommandBuilder(daCustomers);‎

‎// ۴٫ fill the dataset

daCustomers.Fill(dsCustomers, tableName);‎

‎}‎

‎// Update button was clicked‎

public void btnUpdateClicked(object sender, EventArgs e)‎

‎{‎

‎// write changes back to DataBase‎

daCustomers.Update(dsCustomers, tableName);‎

‎}‎

‎// start the Windows form‎

static void Main()‎

‎{‎

Application.Run(new DisconnectedDataForm());‎

‎}‎

‎ }‎

متود Initdata در این لیست حاوی متودهای لازم برای SqlDataAdapter و DataSet می باشد. دقت داشته باشید که آبجکت های متفاوت داده در سطح گروه تعریف شده اند، بنابراین در متودهای متعدد استفاده شوند. پراپرتی DataGrid’s DataSource در سازنده تنظیم می شود. هرزمان که یک یوزر روی کلید Update کلیک می کند، متود Update در بررسی کننده ی رویداد فراخوانده می شود و تغییرات را به پشت دیتابیس می فرستد.

خلاصه:

DataSet ها جدول های متعددی در خود دارند و می توانند در حافظه مانده و مجددا استفاده شوند. SqlDataAdapter شما را قادر می سازد تا یک DataSet را پر کرده و تغییرات را آپدیت کنید. لازم نیست نگران بازکردن و بستن SqlConnection باشید، زیرا SqlDataAdapter این کار را به طور خودکار انجام می دهد. SqlCommandBuilder فرمان های insert، update و delete را براساس عبارت انتخاب SqlDataAdapter پر می کند. متود Fill از SqlDataAdapter را برای پر کردن یک DataSet با داده انتخاب کنید. متود Update مربوط به SqlDataAdapter را فرابخوانید تا تغییرات را به پشت دیتابیس ببرید.