DataReader و DataSet دو شی ارائه شده در ADO.NET به منظور دستیابی به داده می باشند . اشیاء فوق امکانات متعددی برای دستیابی به داده در برنامه های دات نت را در اختیار پیاده کنندگان قرار می دهند . Scott Mitchell اخیرا" در مقاله ای جامع که بر روی سایت http://www.4guysfromrolla.com منشتر شده است به بررسی دو شی فوق پرداخته و آنان را از زوایای متفاوتی مقایسه و در نهایت به این نتیجه رسیده است که استفاده از DataReader در برنامه های وب دارای مزایای بمراتب بیشتری نسبت به DataSet است . برای آشنائی با دلایل وی برای رسیدن به نتیجه فوق ، خلاصه ای از مقاله وی را در ادامه با هم مطالعه می کنیم .
مبانی و اصول اولیه DataReader
DataReader و DataSet دارای وظایف متفاوتی بوده و با اهداف مختلفی طراحی و پیاده سازی شده اند :
- DataSet : یک بانک اطلاعاتی کوچک در حافظه
- DataReader: ترابری داده بین لایه بانک اطلاعاتی و یک برنامه دات نت
در ADO.NET یک provider شامل تعدادی منبع است و کلاس های خاص مرتبط با هر provider به منظور کار با ارائه دهندگان مربوطه ارائه شده است . مثلا" کلاس های SqlConnection, SqlCommand, SqlDataAdapter و SqlDataReader جهت کار با SqlClient provider و کلاس های OleDbConnection, OleDbCommand, OleDbDataAdapterو OleDbDataReader جهت کار با OleDb provider ارائه شده اند.اشیائی که شامل یک پیشوند با نام یک provider می باشند ( نظیر Sql,OleDb,Oracle و ... ) ، اشیاء مختص و وابسته به Provider بوده و به منظور کار با یک Provider خاص طراحی و پیاده سازی شده اند.
DataReader یکی از اشیاء فوق است ( SqlDataReader, OleDbDataReader ) .به منظور استفاده از شی فوق می بایست در ابتدا یک connection به منبع داده ایجاد و query مورد نظر جهت اجراء مشخص گردد . در ادامه DataReader ایجاد و به عنوان یک پل ارتباطی بین برنامه دات نت و منبع ذخیره سازی داده ایفای وظیفه می نماید . مثلا" می توان از کد زیر در این رابطه استفاده نمود :DataReader در هر لحظه یک رکورد را از منبع ذخیره سازی داده load می نماید . هر مرتبه که متد Read شی DataReader فراخوانده گردد ، DataReader رکورد جاری را کنارگذاشته و با مراجعه به بانک اطلاعاتی ، رکورد بعدی را بازیابی می نماید .در صورتی که یک سطر از بانک اطلاعاتی load شده باشد ، متد Read مقدار True و اگر رکوردی برگردانده نشود ، مقدار False برگردانده خواهد شد .کد:' Create command Dim myCommand as New SqlCommand(myConnection, SQL query or stored procedure) ' Create a DataReader to ferry information back from the database Dim myReader as SqlDataReader myReader = myCommand.ExecuteReader() 'Iterate through the results While myReader.Read() '... Work with the current record ... End While ' Close the connection (will automatically close the reader) myConnection.Close()
DataReader ، یک شی داده Connected بوده و نیازمند وجود یک اتصال فعال با بانک اطلاعاتی است . بخاطر داشته باشید که DataReader صرفا" مکاینزم لازم برای ترابری داده بین برنامه و بانک اطلاعاتی را ارائه نموده و پس از قطع connection ، امکان برگرداندن اطلاعات به بانک اطلاعاتی وجود نخواهد داشت . DataReader دارای ویژگی فقط خواندنی و فقط به سمت جلو می باشد . این بدان معنی است که اطلاعات بازیابی شده از بانک اطلاعاتی را نمی توان با استفاده از DataReader تغییر و یا اقدام به بازیابی رکوردها به صورت تصادفی نمود . DataReader محدود به دستیابی رکوردها به صورت ترتیبی ( از اولین رکورد به سمت آخرین رکورد ) است .
مبانی و اصول اولیه DataSet
DataSet یک شی بمراتب پیچیده تر و با ویژگی های بیشتر در مقایسه با DataReader است . در حالی که DataReader به سادگی عملیات برگرداندن داده از یک منبع داده را برعهده دارد ، DataSet را می توان به منزله یک بانک اطلاعاتی مقیم در حافظه تصور نمود . DataSet همانند یک بانک اطلاعاتی از مجموعه ای جدول تشکیل شده است . یک DataSet از مجموعه ای شی DataTable تشکیل می گردد . همانگونه که یک بانک اطلاعاتی می تواند دارای ارتباطاتی بین جداول مربوطه به خود باشد ( به همراه محدودیت های متفاوتی در ارتباط با فیلدهای تعریف شده در هر یک از جداول ) ، یک DataSet نیز می تواند دارای ارتباطات مشخص بین اشیاء DataTable مربوط به خود و محدودیت های لازم برروی فیلدهای DataTable باشد .
برخلاف DataReader ، یک DataSet یک شی داده مستقل از Provider است و در این رابطه اشیائی نظیر SqlDataSet و یا OleDbDataSet وجود ندارد و این مسئولیت شی DataAdapter مربوط به Provider است که داده مختص provider را درون یک DataSet مستقل ( نه یک provider خاص ) ترجمه نماید . کد زیر نحوه استفاده از DataSet را نشان می دهد :همانگونه که در کد فوق مشاهده می گردد ، متد Fill مربوط به شی DataAdapter مسئولیت پر نمودن DataSet را با توجه به query مورد نظر برعهده دارد . در پس پرده ، از یک DataReader به منظور خواندن نتایج اجرای query و پر نمودن DataSet استفاده می گردد. DataSet یک شی داده disconnected است. این بدان معنی است که پس از استقرار داده در DataSet ، می توان connection را غیرفعال ( close ) و همچنان بررسی و پردازش لازم بر روی داده های موجود در DataSet را انجام داد .کد:' Establish Connection Dim myConnection as New SqlConnection(connection string) myConnection.Open() ' Create command Dim myCommand as New SqlCommand(SQL query or stored procedure, myConnection) ' Create the DataAdapter Dim myDataAdapter as New SqlDataAdapter(myCommand) ' Create the DataSet Dim myDataSet as New DataSet ' Fill the DataSet myDataAdapter.Fill(myDataSet) ' Close the connection myConnection.Close() '... Work with the contents of the DataSet ...
با توجه به این که DataSet یک مجموعه از داده های غیرمتصل جداگانه را ارائه می نماید ، امکان ویرایش و دستیابی تصادفی به اطلاعات موجود در آن وجود خواهد داشت . دو ویژگی فوق در DataReader وجود ندارند . علاوه بر موارد فوق ، DataSet دارای پتانسیل های قدرتمندی به منظور کار با اسناد XML است . مثلا" می توان با استفاده از متد WriteXml اطلاعات موجود در یک DataSet را درون یک فایل XML مستقر و یا می توان اطلاعات موجود در یک فایل XML را با استفاده از متد ReadXml شی DataSet خواند و در یک DataSet مستقر نمود .
DataReader و یا DataSet
صرفنظر از این که از DataSet و یا DataReader به منظور بازیابی داده های موجود در بانک اطلاعاتی استفاده می گردد ، می توان به منظور نمایش داده های مورد نظر از کنترل های DataList, DataGrid و یا Repeater با استفاده از یک کد مشابه استفاده نمود . بدین منظور لازم است که خصلت DataSource هر یک از کنترل های فوق به DataReader و یا DataSet نسبت داده شده و در ادامه متد DataBind مربوطه ( کنترل های DataList, DataGrid و یا Repeater ) فراخوانده گردد .
کار با داده ها در ASP.NET بسیار ساده است بگونه ای که معمولا" پیاده کنندگان برنامه های وب ASP.NET هرگز این موضوع را به ذهن خود خطور نخواهند داد که بهترین شی که می توان از آن به منظور دستیابی به داده استفاده نمود ، چیست ؟ آنان بر این عقیده هستند که همه چیز معادل هم بوده و خیلی مهم نخواهد بود که از کدام شی در این رابطه استفاده می گردد .
آیا واقعا" همه چیز یکسان و معادل می باشد ؟ به وضوح مشخص است که بین ویژگی ها و پتانسیل های ارائه شده توسط هر یک از اشیاء DataReader و DataSet تفاوت های عمده ای وجود دارد . DataSet ویژگی های بمراتب بیشتری را در اختیار پیاده کنندگان قرار می دهد و همین موضوع باعث شده است که کارآئی آن برای خواندن داده نسبت به DataReader کمتر گردد .
بر اساس مطالعه انجام شده در رابطه با سرعت بازیابی داده در ADO.NET ، سرعت و کارآئی DataReader سی مرتبه بیش از DataSet می باشد . در بررسی انجام شده بر روی یکهزار رکورد بازیابی شده ، مشخص شده است که DataSet سی مرتبه کندتر از DataReader است ( 89 / 8 ثانیه در مقابل 29 /0 ثانیه ) .
موارد استفاده مفید از DataSetصرفنظر از محدودیت های DataSet از بعد کارآئی ، در مواردی لازم است که از این شی استفاده گردد و گرنه شی فوق به عنوان یکی از عناصر کلیدی در فریمورک دات نت محسوب نمی گردید . استفاده از DataSet در یکی از دو مورد زیر می تواند مفید واقع شود :
- برنامه های Desktop : فرض کنید دارای یک برنامه ورود اطلاعات desktop-based باشیم . یک کاربر برنامه را اجراء ، داده هائی خاص را از برخی بانک های اطلاعاتی load و پس از اعمال تغییرات لازم آنان را در بانک اطلاعاتی ذخیره می نماید . وضعیت فوق یک حالت ایده آل برای DataSet است و امکان خواندن داده ها از درون یک DataSet مستقر در حافظه کامپیوتر سرویس گیرنده ، وجود خواهد داشت . بدین ترتیب کاربران می توانند با داده ها بدون نیاز به ارتباط مستمر با بانک اطلاعاتی کار کنند . پس از اتمام عملیات ویرایش داده ها ، به منظور اعمال تغییرات لازم می توان از یک Batch update استفاده نمود . از آنجائیکه DataSet یک منبع ذخیره سازی داده disconnected است ، امکان دستیابی offline به داده ها وجود خواهد داشت .
چنین وضعیتی ممکن است در یک برنامه وب نیز محقق گردد و لازم باشد که کاربران با برنامه وب همانند آنچه اشاره گردید ، ارتباط برقرار نمایند . آنان یک صفحه وب را مشاهده نموده و پس از اعمال تغییرات لازم ، صرفا" با فعال نمودن یک دکمه Update تغییرات را در بانک اطلاعاتی ثبت نمایند .بانک اطلاعاتی مورد نظر بهنگام نمی گردد تا زمانی که دکمه Update فعال گردد . در چنین مواردی می توان از یک Dataset مبتنی بر Session استفاده نمود.- ارسال و یا دریافت از راه دور اطلاعات از بانک اطلاعاتی به منظور برقراری ارتباط بین پلت فورم های متفاوت : با توجه به این موضوع که یک DataSet می تواند به سادگی درون یک فایل XML قرار داده شود و یا از آن خوانده شوند ، به عنوان اولین کاندید برای ارسال اطلاعات بین پلت فورم های متفاوت مطرح می باشد .مثلا" در صورتی که قصد برگرداندن داده بانک اطلاعاتی را از طریق یک سرویس وب داشته باشید ، یکی از روش های موجود در این زمینه این است که داده های بانک اطلاعاتی درون یک DataSet قرار داده شوند و در ادامه با استفاده از متد سرویس وب، DataSet برگردانده شود . در چنین حالتی DataSet به صورت اتوماتیک درون یک فایل XML قرار داده شده و ارسال می گردد .
علل استفاده از DataSet و علل عدم استفاده از DataSetدر برنامه های وب به مواردی برخورد می کنیم که شاید استفاده از DataSet تنها گزینه موجود در این رابطه باشد . مثلا" فرض کنید قصد داریم برخی اطلاعات موجود در بانک اطلاعاتی را Cache نموده تا از آنان در صفحات متعددی بر روی یک سایت استفاده گردد . این نوع داده ها ممکن است وابسته به نوع کاربر بوده و در Session ذخیره شده باشند و یا ممکن است توسط تمامی کاربران استفاده گردند . در چنین مواردی می بایست اطلاعات را در Data Cache ذخیره نمود .
DataReader با توجه به این که یک شی disconnected است ، نمی تواند برای Cache کردن داده ها مورد استفاده قرار گیرد و در زمان استفاده از آن می بایست اتصالات به بانک اطلاعاتی فعال و بسیار کوتاه باشند ( Short-Live ) . با توجه به موارد فوق در صورتی که قصد دارید داده های بانک های اطلاعاتی را Cache نمائید ، استفاده از DataSet می تواند یکی از گزینه های موجود در این رابطه باشد .ولی آیا این تنها گزینه موجود است ؟ در چنین مواردی می توان یک کلاس را ایجاد که دارای خصلت هائی متناظر و مرتبط با فیلدهای بانک اطلاعاتی است که قصد ذخیره آنان در یک DataSet را دارید . در زمان Cache نمودن داده می توان از یک DataReader به منظور خواندن query از بانک اطلاعاتی ، بازیابی و حرکت بین رکوردهای برگردانده شده استفاده نمود . در این رابطه لازم است برای هر رکورد یک نمونه کلاس سفارشی شده ایجاد ، خصلت های آن را متناسب با مقادیر موجود در query تنظیم و کلاس سفارشی را به یک ArrayList اضافه نمود . در ادامه می توان اشیاء سفارشی را Cache نمود . روش فوق علاوه بر افزایش کارآئی ، قابلیت پشتیبانی را نیز بهتر خواهد کرد . همچنین می توان این مجموعه از کلاس های سفارشی شده را به یک کنترل وب داده ASP.NET ( نظیر DataList, DataGrid و یا Repeater ) نیز نسبت داد (مشابه استفاده از یک DataSet و یا DataReader ) .
یکی دیگر از مواردی که می تواند دلایل استفاده از یک DataSet را در برنامه های وب توجیه نماید ، زمانی است که قصد دستیابی تصادفی به داده هائی خاص در بین تعدادی رکورد را داشته باشیم . چراکه رکوردهای فوق ممکن است بدفعات استفاده گردند . مثلا" فرض کنید قصد استفاده از یک master/detail DataGrid را داریم که در آن یک ستون از DataGrid شامل رکورد مادر و سایر ستون ها شامل DataGrid دیگر ( مرتبط با سطر فرزند) باشد . در چنین مواردی استفاده از یک DataSet به منظور جمع آوری تمامی رکوردهای فرزند از بانک اطلاعاتی در مقابل این روش که برای هر سطر DataGrid یک query را استفاده نمود ، ترجیح داده می شود . کارآئی روش فوق به تعداد سطرهای موجود در جدول مادر بستگی خواهد داشت . از آنجائیکه یک DataSet سی مرتبه کندتر از یک DataReader است ، اگر بیش از سی رکورد در جدول مادر وجود دارد که قصد نمایش آنان را داریم ، استفاده از یک DataSet می تواند گزینه ای معقول تر در این زمینه باشد تا این که برای هر رکورد مادر یک query را اجراء نمود .
منبع : http://www.4guysfromrolla.com