نوشته شده توسط بهزاد عبدالله زاده
مقدمه
به
عنوان یک
برنامه نویس
وب ، بیشتر
زندگی ما در
کنار کار با
داده ها می
گذرد. معمولا
دیتابیسی
برای ذخیره
داده ها ، کد
هایی برای
بازیابی و
ویرایش داده
ها و صفحاتی
برای نشان
داده ها ایجاد
می کنیم. این
اولین مجموعه
ای از آموزش
ها است که در
طی یک سری
مقالات
یکپارچه ، به
ارائه تکنیک
هایی برای
پیاده سازی هر
چه بهتر این
الگو های
معمول، در ASP.NET 2.0
پرداخته شده
است. ما در این
سری مقاله ها
کارمان را با
پیاده سازی یک
software architecture
که شامل سه لایه
، Data
Access Layer (DAL) با
استفاده ازTyped DataSetsیک لایه Business Logic Layer که بر روی
قوانین تجاری
متمرکز شده و
یک لایه presentation که شامل
مجموعه ای از
صفحات ASP.NET است ،
تشکیل شده
است. در
این مجموعه
مقالات پس از
اینکه
پیکربندی اصلی
ساخته شد ، در
مورد موارد
جزئی تر قدم
به قدم به
تفصیل بحث
خواهد شد. کدهای
هر یک از
مقالات هم به
زبان C# و هم به
زبان VB.NET قابل download و
استفاده است .
در
این مقاله ها
از پایگاه
داده Northwind نسخه Microsoft SQL
Server 2005 Express Edition
استفاده شده
است. کدهای
مربوط به این
دیتابیس در
پوشه App_Data پروژه
همراه این مجموعه،
قرار دارد .
در
این مقاله ما
کار را از
ابتدا با
ساختن لایه Data
Access Layer (DAL) شروع
خواهیم کرد ،
در مقاله دوم
لایه Business
Logic Layer (BLL) را
خواهیم ساخت و
در سومین
مقاله بر رو ی page layout کار
خواهیم کرد.
ما در اولین
مقاله موارد و
نکته های
زیادی را
تصمیم داریم برای
شما تشریح
کنیم پس اگر
موافق هستید
شروع کنیم !
1- ايجاد
لايه دستيابي
به داده(data access layer)
در
هنگام كار با
داده ها يك
گزينه تعبيه ي
منطق مخصوص
داده به صورت
مستقيم و بي
واسطه در لايه
ي نمايش
ميباشد(در
پروژه هاي وب
صفحات ASP.NET لايه
نمايش را
تشكيل مي
دهند) كه اين
شيوه دستيابي
به داده ها را
به شدت با
لايه نمايش
پيوند مي دهد.
روش پيشنهادي
ما جداسازي
لايه نمايش از
منطق دستيابي
به داده مي
باشد. لايه ي
جداگانه
دستيابي به
داده ها Data access layer
و به اختصارDAL
ناميده مي شود.
تمام
كدهايي كه باdatasource كار
مي كنند از
قبيل ايجاد connection
و دستورات SELECT، INSERT، UPDATE، DELETE بايد در DAL جايگذاري
شوند و لايه
نمايش نبايد
هيچگونه ارجاعي
به كدهاي
دستيابي به
داده داشته
باشد بلكه مي
تواند براي هر
درخواست
دستيابي به
داده ها DAL را فراخواني
نمايد. به طور
كلي DAL
شامل متدهايي
براي دستيابي
به داده هاي
پايگاه داده
مي باشد. در
اين مقاله ما
از پايگاه
داده northwind
استفاده مي
نماييم كه
شامل جداول products و categories مي باشد.
در DAL
ما متدهايي
مشابه متدهاي
زير به منظور
كار با داده
ها ايجاد مي
نماييم
GetCategories():
اطلاعات
مربوط به تمام
اقلام را باز
مي گرداند
GetProducts():
اطلاعات
مربوط به تمام
محصولات را
بازمي گرداند
GetProductsByCategoryID(categoryID): تمام
محصولات
مرتبط با يك
دسته خاص را
باز مي گرداند
GetProductByProductID(productID): اطلاعات
مربوط به يك
محصول خاص را
با زمي گرداند
اين متدها
هنگامي كه
فراخواني مي
شوند به پايگاه
داده متصل شده
وquery مربوط به
خود را اجرا
مي نمايند و
نتيجه را باز
مي گردانند.
اين متدها مي
توانند يك dataset و يا datareader كه با بازگردانند..
اما به طور
ايده ال اين
نتايج بايد با
استفاده از اشياي
strongly_typed
بازگردانده
شوند. يك شي strongly_typed شي اي مي
باشد كه شماي
آن در زمان
كامپايل مشخص
مي شود و در
مقابل آن ، شي loosly_typed است كه
شماي آن تا
زمان اجرا نا
شناخته مي باشد.
به عنوان
مثال datareader
وdataset به صورت
پيش فرض اشياي
loosly_typed مي باشند و
شماي آنها
بوسيله
ستونهايي كه
از query پايگاه
داده
بازگردانده
مي شوند در
زمان اجرا
مشخص مي شود.
براي دستيابي
به يك ستون
خاص از يك looselytyped
DataTable از اين
كد استفاده مي
نماييم:
DataTable.Rows [index]["columnName"]
. براي
دستيابي به يك
ستون خاص از
يك stronglytyped
DataTable از اين
كد استفاده مي
نماييم:
DataTable.Rows [index].columnName
براي
بازگرداندن
اشياي strongly_typed برنامه
نويس مي تواند
از custom business object و يا typed
dataset
استفاده نمايد.
يك business object توسط
برنامه نويس
به صورت كلاسي
كه خواصش (property) بيانگر
ستونهاي جدول
پايگاه داده
مي باشد، پياده
سازي مي شود. و
يك typed dataset كلاسي
است كه توسط vs بر اساس
شماي پايگاه
داده ايجاد مي
شود و اعضاي
آن بر اساس
اين شما قويا
تعريف مي
شوند.
ما
در اين مقاله
از strongly_typed
dataset
استفاده مي
كنيم . شكل 1
گردش كار بين
لايه هاي
مختلف يك application
را كه از typed dataset
ها استفاده مي
كند، نشان مي
دهد.
شكل1:
تمامي كدهاي
دستيابي به
داده به DAL
محول مي شود
ايجاد
يك Typed
dataset و table adapter
ساختDAL
را با اضافه
كردن يك typed dataset
به پروژه آغاز
ميكنيم. بدين
منظور برروي project
در solution explorer راست كليك
كرده و add new item را
انتخاب
نماييد. گزينه
dataset را
از ليست
انتخاب
نماييد و آن
را northwind.xsd نامگذاري
كنيد.
شكل
2: اضافه كردن dataset
به پروژه
سپس
designer
مربوط
به typed dataset
نمايش داده مي
شود و wizard مربوط به
ساختار بندي table adapter
كه به شما
امكان اضافه
كردن اولين tableAdapter
به typed dataset را مي دهد
آغاز به كار
مي نمايد.
يك
typed dataset به صورت يك
مجموعه ي strongly_typed
از داده مي
باشد و تركيبي
از نمونه هاي strongly_typed datatable مي
باشد كه هر يك
از آنها نيز
تركيبي از
نمونه هاي strongly_typed datarow
مي باشند. ما
براي هر جدول
پايگاه داده
كه مي خواهيم
از آنها در
پروژه
استفاده
نماييم يك strongly_typed datatable
ايجاد مي
نماييم .
ابتدا با
ايجاد يك datatable براي
جدول product
شروع مي
نماييم.
به
خاطر داشته
باشيد كه strongly_typed datatable
هيچ اطلاعاتي
در مورد نحوه
ي دستيابي به داده
هاي جدول
مربوط به خود
ندارد. به
منظور
بازيابي داده
ها از جدول و
بارگذاري
آنها در datatable ، از كلاس dataadapter استفاده
مي نماييم.
براي products
datatable ، tableadapter شامل
متدهايGetProducts()،GetProductByCategoryID(categoryID)، مي باشد،
كه قابل
فراخواني از
لايه نمايش مي
باشند. datatable
به صورت اشياي
strongly_typed ميباشد كه
نقش پاس دهنده
داده بين لايه
ها را بر عهده
دارد.
Wizard ساختار
بندي tableadapter ، با
درخواست انتخاب پايگاه
داده مورد نظر
آغاز مي شود. Drop_down ليست
پايگاه داده
هاي server explorer
را نشان مي
دهد. اگر
پايگاه داده northwind را در server
explorer اضافه
نكرده ايد مي
توانيد دكمه ي
new
connection را به
منظور اضافه
كردن آن كليك
كنيد.
شكل
3: انتخاب
پايگاه داده northwind از drop_down
ليست
پس
از انتخاب
پايگاه داده ،
در مورد ذخيره
سازي connection string در فايل web.config پرسش مي
شود. با ذخيره
سازي connection string در اين
فايل از كد
كردن آن در
كلاسهاي tableadapter بي نياز مي
شويم و همچنين
اين مورد
اعمال تغييرات
احتمالي connection
string را در
آينده، آسان
مي نمايد. با
پذيرش ذخيره
سازي connection string در web.config
، vs آن را در
قسمت <connectionstring>
ذخيره مي
نمايد كه مي
توانيد آن را
به منظور ارتقاي
امنيت
رمزگذاري
نماييد.
شكل4:
ذخيره سازي connection
string در web.config
سپس
ما بايد طرح
اولين strongly_typed datatable را تعريف
نماييم و
اولين متد tableadapter را ايجاد
كنيم. با ايجاد
query كه نتيجه ي
آن
بازگرداندن
ستونهاي مورد
نظر از جدولي
كه مي خواهيم
در datatable منعكس
شود، مي باشد
اين دو مرحله
همزمان انجام
مي شوند. در
انتهاي wizard يك نام متد،
به اين query
نسبت مي دهيم.
اين متد مي
تواند از لايه
نمايش فراخواني
شود. اين متد query تعريف شده
در خود را اجرا
مي نمايد و
نتيجه را در strongly_typed
datatable
بارگذاري مي
نمايد.
براي
تعريف SQL query مي
توانيم يك
دستور خاص sql ايجاد
نماييم و يا
از يك stored procedure كه قبلا
تعريف شده است
استفاده
نماييم و يا يك
stored
procedure جديد
ايجاد نماييم.
شكل
5
زماني
كه اولين متد
را در tableadapter
تعريف مي
نماييم در
حقيقت مي
خواهيم
ستونهايي كه query
باز
ميگرداند در datatable مربوطه نشان
داده شود. query مورد نظر
ما در اين بخش
تمام سطرها و
ستونهاي جدول products را بازمي
گرداند.
شكل
6: وارد كردن sql
query در textbox
علاوه
بر تعريف query به صورت
دستي در
textbox مي توانيم
از querybuilder استفاده
نماييم و به
صورت گرافيكي query مورد نظر
را بسازيم
.
شكل7:
ايجاد query
به صورت
گرافيكي با
استفاده از query
editor
پس از
ايجاد query
و قبل از
اجراي مرحله
بعد دكمه advanced optiones كليك
نماييد. در
پروژه هاي وب
سايت گزينه
اول “Generate Insert، Update، and Delete statements” تنها گزينه
انتخاب شده به
صورت پيش فرض
مي باشد .
درپروژه هاي
ويندوز گزينه
دوم “Use optimistic concurrency” نيز به طور
پيش فرض
انتخاب شده
است.
شكل 8
با انتخاب
دكمه next
مرحله نهايي
ظاهر مي شود.
در اين قسمت
در مورد متدهايي
كه مي خواهيم
به tableadapter اضافه شود
سوال پرسيده
مي شود. دو
الگو به منظور
بارگذاري
داده وجود
دارد
1-
Fill a datatable :
با اين شيوه
متدي ايجاد مي
شود كه يك datatable به عنوان
يك پارامتر مي
پذيرد و بر
اساس نتيجه query ،datatable
را پر مي كند.
كلاس dataadapter
در ADO.NET اين روش را
با متدfill()
پياده سازي
مينمايد.
2-
Return a datatable:
با استفاده از
اين شيوه متد
ايجاد مي شود
و datatable را پر مي
كند و آن را به
عنوان مقدار
بازگشتي متد،
بازمي گرداند
مي توان يك
ويا هر دو
الگو را
استفاده
نمود.هم چنين
مي توانيم نام
متد ها را در
اين مرحله تغيير
دهيم. ما در
اين مرحله هر
دو checkbox را انتخاب
مي نماييم اما
در ادامه تنها
از الگوي دوم
استفاده مي
تماييم. و متد getdata را به getproducts تغيير نام
مي دهيم.
اگر checkbox سوم “GenerateDBDirectMethods،”
را انتخاب
نماييم
متدهاي insert()،update() وdelete() برايtableadapter ايجاد مي
شوند. اگر اين
گزينه انتخاب
نشود تمام به
روز رساني ها
بايد از طريق
متد update()
مربوط بهtableadapter اعمال
شوند.
در
صورتيكه
گزينه “Generate Insert، Update، and Delete statements”
را از advanced properties انتخاب
نكرده باشيد
تنظيمات
گزينه GenerateDBDirectMethods،”" بي
اثر خواهد
بود.
Wizard با كليك
كردن دكمه finish
به پايان مي
رسد. پس از
بسته شدن wizard، DataSet
Designer ، datatable كه هم
اكنون ايجاد
كرده ايم را
نشان ميدهد.
ليست ستونها
را در Products DataTable و به علاوه
متدهاي ProductsTableAdapter
(Fill() ,GetProducts()) را مي توان
مشاهده نمود.
اكنون يك typed
dataset به
همراه يك (Northwind.Products)
datatable و يك
كلاس tronglytypedDataAdapter
(NorthwindTableAdapters.ProductsTableAdapter) با متد GetProducts() داريم.
اين اشيا
مي توانند به
منظور
دستيابي به
ليست تمام
محصولات به
كار برده شوند
:
هر شي كه
در اين مثال
به كار برده
مي شود يك شي strongly_typed مي باشد و
به VS اجازه مي
دهد چك نوع ر ا
در زمان
كامپايل
انجام دهد. و
نيز datatable
بازگردانده
شده توسط tableadapter مي تواند
به تمام data web control ها مانند GridView,
DetailsView, DropDownList, CheckBoxList, نسبت
داده شوند. مثال
زير انقياد datatable بازگشتي
ازمتد getproducts()
به gridview نشان مي
دهد
مرحله
ي 3: افزودن
متدهاي با
پارامتر به
لايه ي Data Access
تا
اين مرحله،
كلاس ProductsTableAdapter فقط يك
متدGetProducts() داردكه
همه ي productهاي
پايگاه داده
را برمي
گرداند.ممكن
است بخواهيم
اطلاعات
مربوط به يك ProductProduct
هاي يك Category
(مقوله)خاص را
بازيابي
كنيم.براي
افزودن اين چنين
وظايفی (توابعي)
به لايه ي Data Access ، ميتوانيم
متدهايی با
پارامتر بهTableAdapter اضافه
كنيم.
خاص را بازيابي
كنيم يا همه ي
بياييد
متدGetProductsByCategoryID(categoryID) را اضافه
كنيم.جهت افزودن
متد جديد به DAL ، به DataSet Designer
برگرديد ، روي
قسمت ProductTableAdapter راست كليك
كنيد و Add Query را
انتخاب كنيد.
در
ابتدا بايد
مشخص كنيم ،که
از چه طريقي
به پايگاه
داده دسترسي
داشته باشيم:
از طريقad-hoc SQL statement يا
يك stored procedure جديد يا يك stored proceduread-hoc
SQL statement را
انتخاب
كنيم.سپس ازما
پرسيده مي شود
كه مايليد
كدام نوع SQL Query را
به كار گيريد؟
از آنجايي كه
ميخواهيم نام همه
ي Product هاي متعلق
به يك مقوله(category)
خاص را
برگردانيم، در
نتيجه يك عبارت(statement)select كه
سطر
برميگرداند
را مي نويسيم.
موجود؟ اجازه
دهيد
مرحله ي
بعد براي
تعريف SQL query
مورد استفاده
جهت دسترسي به
داده ها
است.از آنجايي
كه مي خواهيم
فقط محصولات
متعلق به يك
مقوله ي خاص
را بر گردانيم،
يك select statementGetProducts()را
استفاده مي
كنيم ، با اين
تفاوت كه در
قسمت where اين عبارت
را مي نويسيم:CategoryID=@CategoryID .پارامتر
CategoryID به
ويزارد TableAdapter
نشان مي دهد
كه اين متدي
كه ما ايجاد
كرده ايم به
يك پارامتر
ورودي از نوع
متناظر (مشخص
شده) نياز
دارد.(namely ، nullable integer ) مشابه متد
در مرحله ي
آخر ميتوانيم
انتخاب كنيم
كدام یک از الگو
هاي date access قابل
استفاده است. براي الگوی
Fill ، نام را به FillByCategoryID
تغيير دهيد
وبراي خروجی(return) الگو
يك DataTable (متدهاي GetX)،
از GetProductsByCategoryID استفاده
كنيد.
بعد از كامپايل
اين ويزارد ، DataSet Designer
شامل متدهاي TableAdapterجديد
است.
جهت
افزودن متد
GetProductByProductID(productID)نیز از همين
تكنيك
استفاده مي
شود.اين Query
هاي پارامتر
دار را مي
توان مستقيما
ازDataSet Designer آزمود.
برای این کار روي
متد در TableAdapter راست
كليك و Preview Data را
انتخاب كنيد، سپس
مقداري را
براي پارامتر
وارد كنيد و Preview
را كليك كنيد.
با متدGetProductsByCategoryID(categoryID) در DAL ، مي
توانيم يك
صفحه ي ASP.NET
ايجاد كنيم
كه فقط
محصولات با يك
category مخصوص را
نشان دهد. مثال
زير تمامی
محصولاتي كه
در مقوله ي
(گروه) Beverages
هستند و CategoryID
مساوي 1 دارند ،
را نشان مي
دهد.
|
Beverages.aspx
<%@ Page
Inherits=”Beverages”
<!DOCTYPE
W3C//DTD XHTML “http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional. dtd”>
<html
<head
<title>Untitled
<link </head> <body>
<form <div> <h1>Beverages</h1> <p>
<asp:GridView CssClass=”DataWebControlStyle”>
<HeaderStyle
<AlternatingRowStyle </asp:GridView> </p> </div> </form> </body> </html>
|
|
Beverages.aspx.cs using System;
using
using
using
using
using
using
using
using
using
using
public partial {
protected void {
ProductsTableAdapter ProductsTableAdapter();
GridView1.DataSource productsAdapter.GetProductsByCategoryID(1); GridView1.DataBind(); } }
|
مرحله ي 4:Insert ، Update ، Delete
كردن داده ها
به طور
معمول ، دو الگو
براي insert ، update وdelete
داده ها
استفاده مي
شود. الگو اول،
كه ما آن را الگو
مستقيم
ديتابيس مي
ناميم، درگير
ساختن
متدهايي است
كه وقتي
درخواست مي شوند
، يك دستورupdate ، insert يا delete
كه تنها روي
يك ركورد
ديتابيس عمل
مي كند، را به
ديتابيس صادر
مي كنند. به
این متدها مقادیری
پاس داده مي
شوند (integer ، string ، Boolean، ِDataTime و…)
كه متناظر با
مقدارهاي
مورد نیاز
برای Insert ، update
يا delete است. براي
مثال، با اين الگو
براي جدولProducts ، متد delete
يك مقدارinteger را به عنوان
پارامتر مي
گيرد، و ProductID
ركوردي را كه
بايد حذف شود
را نشان مي
دهد. متد insert
يك مقدار String
را برايProductName
مي گيرد، يك
مقدار decimal براي UnitPrice ، يك مقدارinteger
براي UnitOnStockو….
الگو ديگر،
كه ما به آن الگو
گروهی می
گوییم(batch update) است. این
الگو ، جهت Update
كردن يك DataSet ،ِDataTable ، يا مجموعه
ای از DataRow ها در
فراخواني يك
متد، بكار مي
روند. با اين الگو
يك developer ، DataRow
ها را در يكDataTable ،update ، insert يا delete مي كند.سپس
اين متد
يكايك DataRow هاي
پاس داده شده
را مي شمرد،
تعيين مي كند
آيا ويرايش،
افزودن يا
حذفي داشته
ايم يا
خير(توسط
مقدار خصوصیت RowState )،
و براي هر ركورد،
عملیات مناسب را
صادر ميكند.
TableAdapter به طور پيش
فرض از الگو batch update
استفاده مي
كند.اما الگو DBdirect
را نیز
پشتيباني
ميكند. از
آنجايي كه
گزينه ي”Generate Insert،Update،and Delete statements”
را از Advanced
Propertise در
زمان ايجاد TableAdapter ، انتخاب
كرديم، ProductsTableAdapter
شامل يك متدupdate()
است كه الگوbatch update را
پياده سازي مي
كند.به طور
مشخص، TableAdapter شامل يك
متد Update()Typed DataSet ، يك Strongly-typed DataTable با يك يا چند DataRow را پاس دهد.
اگر
chechbox
“GenerateDBDirectMethods”را علامت
بزنيد، وقتي
كه براي اولين
بار TableAdapter ايجاد مي
كنيد، الگوDB direct
نيزتوسط
متدهاي insert() ، update() و delete() پياده
سازي خواهد
شد.
است كه
ميتواند
هر دو الگو
تغيير و تبديل
داده از خصوصیت
های InsertCommand، UpdateCommand وDeleteCommand TableAdapter براي صدور
دستورات INSERT،UPDATE
و DELETE
آنها به
پايگاه داده ،
استفاده مي
كنند.
شما مي
توانيد خصوصیت
هاي InsertCommand، UpdateCommand و DeleteCommand را با كليك
كردن روي TableAdapter
در DataSet Designer و با رفتن
به Properties window ،
ويرايش
كنيد.(مطمئن
شويد كه
TableAdapter
را انتخاب
كرده ايد، و
شي ProductTableAdapter در Properties
Window
انتخاب شده
است)
براي
آزمايش يا
ويرايش command properties پايگاه داده
، روي subproperty ، commandText
كليك كنيد. اين
كار باعث مي
شود كه پنجره
ي Query Builder ظاهر شود.
كدي كه در
ادامه نوشته
شده است نشان
مي دهد كه چگونه
از الگوbatch update
براي اضافه
كردن قيمت همه
ي محصولاتي كه
discontinued
نيستندو 25
واحد يا كمتر
درموجودي
داشته باشد،
را نشان مي
دهد.
|
NorthwindTableAdapters.ProductsTableAdapter
new
// For each product، // there are 25 items in stock or less
Northwind.ProductsDataTable products =
foreach (Northwind.ProductsRow product
if (!product.Discontinued && product.UnitPrice *= 2; // Update the products productsAdapter.Update(products);
|
كد زير
چگونگي
استفاده از الگو
DB direct
براي delete يكProduct مشخص و سپس
update و بعد افزودن
يك محصول
جديد از طريق
برنامه نويسي را
نشان مي دهد.
|
NorthwindTableAdapters.ProductsTableAdapter
new
// Delete the productsAdapter.Delete(3);
// Update Chai
productsAdapter.Update(“Chai”،
18.0m،
// Add a new
productsAdapter.Insert(“New
“12 tins per carton”،
|
ايجاد
متدهاي insert, update, delete
به صورت
سفارشي
به منظور
ايجاد يك متد
سفارشي، به DataSet
Designer بازمي
گرديم. بر روي tableadapter
راست كليك
نموده و گزينه
ي Add
query را
انتخاب مي
نماييم، wizard مربوط به tableadapter آغاز مي
شود. در صفحه ي
دوم نوع query را كه مي
خواهيم ايجاد
نماييم، را
مي توانيم
انتخاب كنبم.
مي خواهيم يك
متد كه يك
محصول جديد را
به جدول اضافه
نمايد و productidمربوط
به سطر اضافه
شده را بر
گرداند،
ايجاد نماييم.
بنابراين
گزينه ي insert را
انتخاب مي نماييم.
در صفحه
بعد commandtext
مربوط به
دستور insert ظاهر مي شود.
اين دستور را
با اضافه كردن
SELECTSCOPE_IDENTITY() به انتهاي query تكميل مي
نماييم. اين
دستور identity
مربوط به سطر
اضافه شده را
بازمي گرداند(
;
قبل از دستور select الزامي
است)
در نهايت query جديد
راInsertProduct نامگذاري
مي نماييم
زمانيكه
به dataset
designer باز مي
گرديم متد
جديد به ProductsTableAdapter اضافه شده
است. به صورت
پيش فرض executemode مربوط به متدهاي
insertnonquery
مي باشد. بدین
معنا كه تعداد
ركوردهاي
تغيير يافته
را باز مي
گردانند. در
اين متد خاص
مي خواهيم متد
مقدار
بازگشتي queryرا
بازگرداند،
بدين منظور
خاصيت ExecuteMode
مربوط به متد
را به scalar
تغيير مي
دهيم. ،
كد زير
استفاده از
متد InsertProduct
را در عمل
نشان مي دهد
مرحله
ي 5 :كامل
كردن لايه ي Data Access
توجه كنيد
كه كلاس ProductsTableAdapters مقدارهايCategoryID
وSupplierId را از جدول Productبرمي
گرداند، شامل
ستونCategorysName از جدول Categoriesيا
ستون CompanyName از جدول Suppliers
نمي باشد، اما
در هنگام نشان
دادن اطلاعات product ،مي خواهيم
آنها (CompanyName، CategoryName) را
نيز نشان
دهيم. ما مي
توانيم GetProducts()
را به متد initial
يك TableAdapter بيفزاييم
تا با به روز
رساني strongly-typed Data Table ،شامل
مقدارستونهاي
جديد CompanyName وCategoryName باشد .
اين راه حل
مي تواند
مشكلي را
ايجاد كند،
هرچند كه، متدهايTableAdapter
براي insert،update و deleteبر
اساس این متد
مقدار دهی
اولیه می شوند.
خوشبختانه،
متدهایي كه به
طور خودكار
براي insert،update وdelete ايجاد
ميشوند تحت
تاثيرsubquery ها در شرطSelect
نيستند. با
توجه به این
مسئله و با
احتیاط می
توان با
افزودن query هايمان
به Categories و بصورت subquery، به
غیر از
استفاده joins ،
می توان از
دوباره نوشتن متدهایی
که برای
ویرایش داده
ها بکار می
روند، اجتناب کرد.
روي متد GetProducts() در
ProductsTableAdapterراست
كليك كنيد و
گزينه ي Configure
را انتخاب كنيد.
سپس ،
شرط select را مانند
آنچه در زير
مي بينيد
تنظيم كنيد: Suppliers
|
SELECT
QuantityPerUnit،
(SELECT
WHERE
(SELECT
WHERE
FROM
|
بعد
از تغيير متد
جهت استفاده
از اين query ، DataTable
دو ستون جديد
را نشان خواهد
داد: CategoryNameوSupplierName .
حال
کمی وقت
بگذارید و شرط
select در
متد GetProductsByCategoryID(categoryID) را
نيز تصحیح كنيد.
اگر select متدGetProducts()
را با
استفاده از join ، updateمي كرديد ، DataSet Designer
توانايي
ايجاد خودكار(auto-generate)متدهايي
براي insert،update و delete
داده هاي
پايگاه داده
با استفاده از
الگوي(pattern)DB direct را
نداشت. در عوض،
شما مي توانيد
آنها را به
طور دستي
مانند آنجه
براي متدInsertProduct()
انجام داديم،
ايجاد كنيد.
اگر مي خواهيد
از الگوي به
روز رساني
دسته اي(batch updating
pattern) استفاده
كنيد، مي
توانيد مقدار خاصیت
هايInsertCommand ،UpdateCommand و DeleteCommand را به طور
دستي آماده
كنيد (ايجاد
كنيد).
اضافه
كردن TAbleAdapter هاي باقي
مانده
تا
الان ، ما فقط
با يكTableAdapter
براي يك جدول
پايگاه داده كار
كرديم. پايگاه
داده ي NorthWind
جدولهاي
زيادي دارد كه
ما در طي
پروژه با آنها
كار میكنيم.
يك DataSet مي
تواند شامل
چندين DataTable مرتبط باشد .بنابراين
، براي كامل
كردنDAL
لازم است كه DataTable
هاي ديگر را
اضافه كنيم.
بعد
از ايجادDataTable
ها متد هاي لازم
را به هر table
بيافزاييد.
|
l ProductsTableAdapter ¡ GetProducts:
SELECT
QuantityPerUnit،
ReorderLevel،
Categories
Products.CategoryID)
FROM Suppliers
Products.SupplierID) FROM Products ¡ GetProductsByCategoryID:
SELECT
QuantityPerUnit،
ReorderLevel،
Categories
Products.CategoryID)
(SELECT
Suppliers.SupplierID FROM Products
WHERE
GetProductsBySupplierID
SELECT
QuantityPerUnit،
ReorderLevel،
(SELECT
Categories.CategoryID
as
WHERE
as FROM Products
WHERE ¡ GetProductByProductID
SELECT
QuantityPerUnit،
ReorderLevel،
FROM
Products.CategoryID)
(SELECT
WHERE
as FROM Products
WHERE l CategoriesTableAdapter ¡ GetCategories
SELECT
FROM ¡ GetCategoryByCategoryID SELECT CategoryID، CategoryName، Description FROM Categories
WHERE CategoryID = l SuppliersTableAdapter ¡ GetSuppliers
SELECT
Country، FROM Suppliers ¡
GetSuppliersByCountry
SELECT
City، FROM Suppliers
WHERE Country ¡ GetSupplierBySupplierID
SELECT
City، FROM Suppliers
WHERE l EmployeesTableAdapter ¡ GetEmployees
SELECT
Title، FROM Employees ¡ GetEmployeesByManager
SELECT
Title، FROM Employees
WHERE ¡ GetEmployeeByEmployeeID
SELECT
Title، FROM Employees
WHERE
|
اضافه
كردن كد
سفارشي به DAL
TableAdapter ها و DataTable ها ي
اضافه شده به DataSet
در يك فايل با
شمايXML بيان شده
اند. ميتوانيد
اين اطلاعات
را با راست
كليك روي فايل
NorthWind.xsd در Solution
ExplorerوانتخابView Code ، ببينيد.
اطلاعات
مربوط به اين
شما در زمان
طراحي هنگامي
كه كامپايل مي
شوند و يا در
زمان اجرا (در
صورت نياز) به c# و
يا visual basic
ترجمه مي شود.
براي مشاهده ي
اين كدها كه
به صورت خودكار
ايجاد شده اند
به class view رفته و
كلاسهاي tableadapter
ويا typed dataset را انتخاب
نماييد. با
استفاده از class view
مي توانيد
خواص، متدها و
يا رويدادهاي
مربوط به
كلاسهاي tableadapter
ويا typed datasetرا مشاهده
نماييد. براي
مشاهده ي يك
كد متد خاص بر
روي نام آن در class view دو بار كليك
نماييد و يا
بر روي آن
راست كليك نموده
و گزينه ي go to definition
را انتخاب
نماييد.
با
وجود اينكه
توليد خودكار
كدها باعث
صرفه جويي در
وقت مي شود
اما اين كدها
معمولا بسيار
كلي هستند و
به منظور برآورده
ساختن
نيازمنديهاي
خاص يك برنامه
احتياج به
سفارشي كردن
دارند. ريسك
سفارشي كردن و
دستكاري
كدهايي كه به
صورت خودكار
توليد مي شوند
در اين مسئله
است كه ابزاري
كه كد را به
صورت خودكار
توليد نموده
است ممكن است
تصميم به
توليد دوباره
آن بگيرند و
كدي كه سفارشي
شده است را
تغيير دهد.
مفهوم
كلاسهاي partial در .NET 2.0
شكستن يك كلاس
در قالب
به منظور
نشان دادن
نحوه ي سفارشي
كردن DAL ، متد getproducts()
را به كلاس suppliersrow
اضافه مي
نماييم. كلاس suppliersrow
يك سطر در
جدول suppliers را نشان مي
دهد. هر
فروشنده مي
تواند صفر يه
چند محصول را
فراهم نمايد.
بنا بر اين getproducts()
محصولاتي
فروشنده خاص
را باز مي
گرداند. بدين
منظور يك class file
در پوشه ي App_Code SuppliersRow.cs
مي گذاريم و
كدهاي زير را
به آن اضافه
مي نماييم:
ايجاد نموده و
نام آن را
اين كلاس
جزئي در هنگام
ساخت كلاس Northwind.SuppliersRow به
كامپايلر مي
گويد متد getproducts() تعريف شده
را نيز در نظر
بگيرد.
اكنون مي
توان از متد getproducts() به منظور
محاسبه
محصولات يك
فروشنده خاص
استفاده
نماييم.
اين داده
مي تواند در
هر data
web control نشان
داده شود.
صفحه ي زير از
يك GridView با
دو فيلد
استفاده مي
نمايد.
·
يك BoundField كه
نام هر
فروشنده را
نشان مي دهد
·
يك TemplateField
كه شامل كنترل BulletedList
مي باشد كه
نتيجه ي
بازگشتي از getproducts() براي هر
فروشنده به آن
نسبت داده مي شود
اين مثال
نحوه ي
استفاده از
متد سفارشي
اضافه شده به
كلاس Northwind.SuppliersRow را نشان مي
دهد.

خلاصه
زمانیکه
یک برنامه وب
ایجاد می کنید
DAL باید
اولین گام
باشد و باید
قبل از ایجاد
لایه نمایش
قرار گیرد. با
استفاده از visual
studio،
تولید DAL بر اساس Typed
DataSets کاری
است که باید 10
تا 15 دقیقه از
وقت شما را
بگیرد که نیاز
به نوشتن کدی
ندارد.
جهت دانلود سورس کد روی لینک های زیر کلیک کنید.
ویژوال بیسیک :
http://download.microsoft.com/download/5/d/7/5d7571fc-d0b7-4798-ad4a-c976c02363ce/ASPNET_Data_Tutorial_1_VB.exe
سی شارپ :
http://download.microsoft.com/download/4/6/3/463cf87c-4724-4cbc-b7b5-3f866f43ba50/ASPNET_Data_Tutorial_1_CS.exe
نوشته شده توسط خانم مهندس قدمیاری
Caching
Data at Application Startup
Download the tutorial in PDF format
Download the tutorial in PDF format
- farsi
Cache
کردن
داده ها در هنگام Startup
برنامه
مقدمه:
در
دو مقاله ی قبلی چگونگی cache
کردن
داده ها در لایه ی Presentation
و Caching
Layer را
دیدید.
در
Cache کردن
داده ها با استفاده از ObjectDataSource
, ما
چگونگی استفاده از امکانات cache
کنترل
ObjectDataSource در
لایه ی Presentation
را بررسی
کردیم.
و درمبحث
قبل , به
cache کردن
داده ها در لایه ای جدید و جدا به نام
Caching Layer
پرداختیم.
در هر
دو مقاله ی قبل,
از
بارگذاری القایی(reactive
loading) در
کار با data cache
استفاده
کردیم.
با
استفاده از Reactive
loading , هر
بار که داده ها درخواست می شوند,
سیستم
از وجود داده ها در Cache
اطمینان
حاصل می کند.
اگر
داده ها در Cache
موجود
نباشند, آنها
را از منبع سازماندهی داده ها (برای
مثال یک دیتابیس)
می
گیرد و سپس این داده ها را Cache
می کند.
مزیت
اصلی Reactive loading
پیاده
سازی بسیار آسان این روش است.
یکی از
معایب این روش کارایی متغیر و ناجور آن
در بین درخواست ها است.
فرض
کنید صفحه ای از Caching
Layer مبحث
قبلی جهت نشان دادن اطلاعات Product
استفاده
می کند.
هنگامی
که این صفحه برای اولین بار رویت می
شود یا هنگامی که برای اولین بار بعد از
خارج شدن داده های Cache
شده بعد
از زمان Expire
رویت
می شود, داده
ها باید از دیتابیس بازیابی شود.
بنابراین,
این
درخواست کاربر زمان بیشتری نسبت به درخواست
ذخیره ی اطلاعات دارد.
بارگذاری
پیش گستر(Proactive
loading)
یک
استراتژی برای مدیریت تعاملی Cacheرا
فراهم می کند.
با این
استراتژی,
کارایی
همه ی درخواستها توسط بارگذاری داده های
cache شده
قبل از این که به آنها نیازی باشد,
یکسان
می شود.
به طور
معمول ,
Proactive loading از
یکسری فرایند ها که به طور دوره ای زمان
به روزرسانی داده ها در لایه ی زیرین را
چک می کنند یا خبر می دهند,
استفاده
می کند.
سپس این
فرایند, داده
ها ی Cache را
به منظور تازگی و جلوگیری
از ماندگاری داده ها، بروز رسانی می کند.
روش
Proactive loading
درصورتی
که داده های لایه زیرین ازیک اتصال بسیار
کند با دیتابیس,
یا یک
Web servise یا
سایر data source
های کند
فراهم شوند,
مفید و
کارا است.
اما
این روش در پیاده سازی بسیار دشوار است
زیرا نیازمند ایجاد,
مدیریت
و گسترش و آرایش یک فرایند به منظور چک
کردن تغییرات و به روز رسانی cache
است .
مد
دیگر Proactive loadig
, که
ما قصد توضیح و بررسی آن را داریم,
بارگذاری
داده ها درCache
هنگام
Startup یک
Application است.
این
برداشت برای cache
کردن
داده های استاتیک (مانند
رکوردهای جداول مراجعه(lookup
table) یک
دیتابیس)
بسیار
مفید است.
مرحله
ی 1:
تعیین
داده ها به منظور Cache
در
Application Startup
مثالهای
caching ی
که در دو مبحث قبلی به توضیح وبررسی آنها
پرداختیم , از
reactive loading
استفاده
می کردند و داده ها را به طور دوره ای تغییر
می دادند و زمان گزافی صرف ایجاد، نمی شد.
اما
اگر داده های cache
شده
هرگز تغییر نمی کردند,
زمان
expire ی
که توسط reactive
loading استفاده
شده بود, بیهوده
است.
بعلاوه,
اگر
زمان زیادی صرف تولید داده های cache
شده
شود(cache
خالی
باشد),
کاربر
درخواست کننده ی داده ها باید زمان زیادی
را جهت بازیابی داده ها تحمل کند.
بنابر
این داده های استاتیک و داده هایی که زمان
زیادی صرف ایجادشان می شود را در هنکام
startup برنامه
cache کنید.
هنگامی
که دیتابیس مقدارهای پویا و تغییر پذیر
زیادی دارد ,
ممکن
است مقدار زیادی داده های استاتیک نیز
داشته باشد.از
این جمله می توان به همه ی مدلهای داده یک
یا چند ستون که شامل مقدار مشخصی از یک
مجموعه ی انتخابات هستند,
اشاره
کرد.
برای
مثال در یک دیتابیس ,
جدول
Patients ستونی
به نام PrimaryLanguage
که
مجموعه ای از مقادیر English,
Spanish, French, Russian, Japanese و…
است
را داراست.
بعضی
اوقات, این
نوع ستون ها با استفاده از جداول مراجعه
پیاده سازی می شوند.
این
به نسبت بهتر از ذخیره سازی رشته ای
“English“
یا
“French”
و…
در جدول
Patients است.
جدول
دوم معمولا با دو ستون (
یک
ستون به منظور نگهداری شناسه ی منحصر و
یک ستون جهت تعریف رشته ای با یک رکورد
برای مقدارهای ممکن ومجاز )
ایجاد
می شود.
ستون
PrimaryLanguage در
جدولPatients ,
شناسه
ی منحصر و
مخصوصی متناظر با
جدول مراجعه را نگهداری می کند.
در
شکل زیر , زبان
اصلی John Doe’s
انگلیسی
است حال آنکه زبان اصلی Ed
Johnson روسی
است.
شکل
1:جدول
Languages
,جدول
مراجعه ای است که توسط جدول Patients
استفاده
شده است.
رابط
کاربری که به منظور تغییر یا ایجاد یک
بیمار (patient)
استفاده
می شود,
drop-down list ی
از زبان های رکوردهای جدول Languages
است.
بدون
عمل Cache ,
هر بار
این interface
رویت
شود, سیستم
باید درجدول Languags
جستجویی
انجام دهد.از
آنجا که مقدارهای جدول مراجعه به ندرت
تغییر می کنند,
این
کاری اضافی و غیر ضروری است.
اگرچه
reactive loading از
منقضی شدن بر مبنای زمان استفاده می کند
و برای داده های استاتیک جدول مراجعه
نیازی به منقضی شدن ندارد,
اما می
توانیم جهت cache
کردن
داده های Languages
از
reactive loading ی
شبیه آنچه در مبحث قبل بکارگرفته شد,
استفاده
کنیم.
دراین
مبحث ما به بررسی چگونگی cache
کردن
داده های
جدول مراجعه و دیگر
اطلاعات استاتیک می پردازیم.
مرحله
ی 2:
آزمودن
روشهای مختلف cache
کردن
داده ها
در
application های
asp.net ,
می
توانید اطلاعات را از طریق برنامه نویسی
cache کنید.
اشیا
(object) را
نیز می توانید با استفاده از static
members یا
application state
, cache کنید.
وقتی
با یک کلاس کار می کنید,
برای
این که اعضای کلاس در دسترس باشند باید
یک نمونه از آن کلاس را ایجاد کنید.
برای
مثال, جهت
درخواست یک تابع از کلاسی درBusiness
Logic Layer ابتدا
باید نمونه ای از آن کلاس را ایجاد کنیم:
|
ProductsBLL productsAPI.SomeMethod();
productsAPI.SomeProperty |
قبل
از اینکه بتوانیم با متد یا خصوصیت خاصی
از کلاسی کار کنیم ,
باید
نمونه ای از آن کلاس را با استفاده از کلمه
ی new ,
ایجادکنیم.
متدها
و خصوصیت
ها با یک نمونه ی
خاص پیوند خورده اند.
Lifetime این
اعضا به lifetime
شیی که
به آن متصل هستند گره خورده است.از
طرف دیگر,
اعضای
استاتیک,
خصوصیات
و متدهایی متغیری هستند که در میان همه ی
نمونه های یک کلاس مشترک هستند,
ودر
نتیجه lifetime
آنها
به بلندی lifetime
یک کلاس
است.
اعضای
استاتیک توسط کلمه ی کلیدی static
مشخص
می شوند.
علاوه
بر اعضای استاتیک,
داده
ها نیز می توانند با استفاده ازstate
application ,
cache شوند.
هر
application در
ASP.NET مجموعه
ای از نام/مقدار،
که دربین همه ی
کاربران و صفحات application
مشترکند,
را
نگهداری می کنند.
این
مجموعه با استفاده از خصوصیت Application
کلاس
HttpContext
قابل
دسترسی است.
استفاده
از آن در code-behind
به صورت
زیر است:
|
Application["key"]
object |
Data
cache , API
بسیار
غنی برای cache
کردن
داده ها فراهم می کند.
همچنین
مکانیزمی برای منقضی شدن بر مبنای زمان
یا بر مبنای وابستگی وتعلق,
فراهم
می کند. و
اولویت آیتمهای cache
را تعیین
می کند.
با
وجود اعضای استاتیک و application
state , بعضی
ویژگی ها باید توسط برنامه نویس به طور
دستی افزوده شود.
در
این مبحث ما کد مربوط به هر سه تکنیک Cache
کردن
داده های استاتیک را مورد بررسی قرار می
دهیم.
مرحله
ی 3:
Cache کردن
داده های جدول Suppliers
جداول
دیتابیس Northwind
از
هیچگونه جداول
مراجعه ای استفاده نکرده اند.
4 جدولی
که در DAL ایجاد
کردیم, فاقد
داده با مقدار استاتیک بودند.به
جای صرف وقت به منظور افزودن table
ی جدید
به DAL و
سپس افزودن کلاسی جدید در BLL
, اجازه
دهید طوری وانمود کنیم که داده های
جدولSuppliers استاتیک
هستند.
بنابراین,
میتوانیم
داده های این جدول را در Application
startup , cache
کنیم.
کار
را با ایجاد کلاسی جدید به نام staticCache.cs
در پوشه
ی cl شروع
کنید.
شکل2:ایجاد
کلاس StaticCache.cs
در
پوشه ی cl
باید
متدی جهت بارگذاری(load)
داده
ها درstartup که
مقدار برگشتی آن داده ها ی cache
است,
اضافه
کنیم.
|
[System.ComponentModel.DataObject]
public class {
private
public static {
// Get
using a
SuppliersBLL
suppliers = }
[DataObjectMethodAttribute(DataObjectMethodType.Select,
public static {
return } } |
قطعه
کد بالا از یک عضو متغیر استاتیک به نام
supplier استفاده
می کند.
این
عضو نتیجه
ی برگشتی متد GetSuppliers()
کلاس
SuppliersBLL که
توسط متد LoadStaticCache()
فراخوانی
می شود, را
نگهداری می کند.
متد
LoadStaticCashe() در
زمان ابتدای application
فراخوانی
می شود.
این
داده ها در آغاز application
یکبار
بارگذاری(load)
می
شوند, و
هر صفحه ای که نیازمند کار با داده های
supplier است,
می تواند
متد GetSuppliers()
کلاس
StaticCache را
فراخواند.
بنابراین,
فراخوانی
دیتابیس جهت گرفتن اطلاعات supplierها
تنها یکبار و آنهم در زمان آغاز application
صورت
می گیرد.
ما
می توانیم متناوبا از application
state یا
data cache استفاده
کنیم.
قطعه
کد زیر کلاسی با امکان استفاده از
application state را
نشان می دهد:
|
[System.ComponentModel.DataObject]
public class {
public static {
// Get
using
SuppliersBLL
HttpContext.Current.Application["key"] }
[DataObjectMethodAttribute(DataObjectMethodType.Select,
public static {
return } } |
در
متد loadStateCache()
, اطلاعات
supplier در
متغیری با سطح دسترسی application
ذخیره
می شود.
مقدار
برگشتی آن متناسب با نوع متد GEtSuppliers()
است.
در
صورتی application state
در دسترس
است که درکلاسهای Code-behind
صفحات
Asp.Net از
Application[“key”]
استفاده
شود و باید در معماری از
HttpContext.Current.Application[“key”]
جهت
گرفتن HttpContext
جاری
استفاده کرد.
بعلاوه
data cache میتواند
همچون یک انبار cache
استفاده
شود.
اینچنین
که در کد زیر می بینید:
|
[System.ComponentModel.DataObject]
public class {
public static {
// Get
using the
SuppliersBLL HttpRuntime.Cache.Insert(
/* key */
/* value */
/*
/*
/*
/* priority
/* }
[DataObjectMethodAttribute(DataObjectMethodType.Select,
public static {
return } } |
جهت
افزودن یک آیتم به data
cache بدون
expire مبتنی
بر زمان از
مقدارهای System.Web.Cache.NoAbsoluteExpiration
و
System.Web.Caching.Cache.NoSlidingExpiration
به
عنوان پارامترهای ورودی استفاده کنید.
به
علت این که بتوانیم
اولویت آیتم های cache
را تعیین
کنیم, این
overload خاص
متد Insert متعلق
به cache data
را
انتخاب کردیم.
این
اولویت بندی به منظور تعیین آیتمی است که
در زمان کمبود حافظه در دسترس
باید از cache
خارج
شود.
در
اینجا ما از اولویت NotRemovable
استفاده
کرده ایم.
این
اولویت ما را
از این که داده ها ازcache
خارج
نمی شوند,
مطمئن
می کند.
مرحله
ی 4:
اجرای
کد در زمان startup
یک
Application
جهت
اجرای کد در زمانی که Application
برای
اولین بار شروع می شود,
لازم
است فایل مخصوصی با نام Global.asax
ایجاد
شود.این
فایل می تواند شامل event
handler هایی
برایapplication ,
session و
رویدادهای سطح درخواست(request-level
) باشد.
در این
فایل می توانیم کدهایی را بیفزاییم که هر
زمان application
شروع
می شود, اجرا
شوند.
یک
فایل Global.asax
را به
دایرکتوری ریشه ی Application
تان
اضافه کنید.
جهت
انجام این کار ,
روی اسم
وب سایتتان در Solution
Explorer راست
کلیک کنید و گزینه ی Add
New Item را
انتخاب کنید.در
diolog box ظاهر
شده, آیتم
Global Application Class
را
انتخاب کنید و دکمه ی Add
را کلیک
کنید.
توجه:
اگر
فایلGlobal.asax
را از
قبل در پروژه ای که ایجاد کرده اید,
داشته
باشید, آیتم
Global Application Class
در لیست
این dialog box((Add
New Itemنخواهد
بود.
شکل
3:
افزودن
فایلGlobal.asax
به
دایرکتوری اصلی Web
Application
الگوی
فایل Global.asax
به طور
پیش فرض شامل 5
متد
با یک تگ script
سمت
سرور(server-side)
است
:
-
Application_Start
–هنگامی
که web application
برای
اولین بار آغاز می شود,
اجرا
می شود. -
Application-end
–زمانی
که application در
حال بسته شدن است,
اجرا
می شود. -
Application_Error
–هر
زمان که یک exception
کنترل
نشده(unhandled)
از
Application برسد,
اجرا
می شود. -
Session_Start
–هنگامی
که یک session
جدید
ایجاد شود,
اجرا
می شود. -
Session_End
–زمانی
که یک session
منقضی
یا فاسد شود ,
اجرا
می شود.
Application_Start
تنها
یکبار در طول حیات application
فراخوانی
می شود.و
اجرای آن تا زمانی که Application
دوباره
شروع نشده است(restart),
ادامه
دارد. این
متد می تواند به دلیل ویرایش محتویات پوشه
ی /bin ,
ویرایش
Global.asax ,
ویرایش
محتویات پوشه ی App_Code
, یا
ویرایش فایل Web.Config
, یا
دلایل دیگر اتفاق افتد.
در
این مبحث , ما
تنها به متد Application_Start
, کدها
و دستوراتی را می افزاییم,
بنابراین
می توانید بقیه ی قسمتها را حذف کنید.
در
Application_Start ,
متد
LoadStaticCache()
کلاس
StaticCache را
که اطلاعات تولید کننده(Supplier)
را
لود کرده و آنها را cache
می کند
, را
فرا می خوانیم.
|
|
درstartup
این
application ,
متد
LoadStaticCache()
اطلاعات
تولید کننده را از BLL
می گیرد,
و
آن را در یک متغیر
استاتیک ذخیره می
کند.
برای
بررسی این عملکرد ,
یک
breakpoint درمتد
Application_Start
قرار
دهید و آن را اجرا کنید.
توجه
کنید که breakpoint
به محض
اینکه application
آغاز
می شود, فعال
می شود(روشن
می شود).
درخواستهای
بعدی سبب اجرای متد Application_Start
نمی
شوند.
شکل4:استفاده
از breakpoint
جهت
بررسی عملکردevent
handler (کنترلگر
رویداد)
Applicaqtion_Startی
در حال اجرا
توجه:
اگر
breakpoint مربوط
به Application_Start
در زمان
شروع اولین debug
موفق
نبود, به
این دلیل است که application
تان
قبلا شروع شده است.
Application تان
را با ویرایش Global.asax
یا
فایلهای Web.CXonfig
مجبور
به restart کنید
و دوباره سعی کنید.
می
توان با افزودن(یا
حذف)
یک
خط خالی در آخر هر کدام ازاین فایلها ,
applicationتان
را خیلی ساده و سریع restart
کنید.
مرحله
ی 5:نمایش
داده های cache
شده
در
آغازapplication ,
کلاس
StaticCache
محتوی
یک نسخه cache
شده از
داده های supplier
است که
میتواند در متد GetSuppliers()
در دسترس
باشد.
جهت کار
با این داده ها در لایه ی presentstion
, می
توانیم از یک
ObjectDataSource
استفاده
کنیم یا از طریق برنامه نویسی متد
GetSupplier() کلاس
StaticCache را
از code-behind صفحه
درخواست کنیم.
بیاید
چگونگی بکارگیری کنترلهای
ObjectDataSource و
GridView جهت
نمایش دادن اطلاعات supplier
(تولیدکننده
ی) cache
شده را
با هم بررسی کنیم.
کار
را با بازکردن صفحه ی AtApplicationStartup.aspx
در پوشه
ی Caching ,
شروع
کنید.
یک
GridView ازToolBox
به
designer اضافه
کنید, خصوصیتID
آن
را Suppliers کنید.
سپس در
تگsmart متعلق
بهGridView ,
یک
ObjectDataSource جدید
با نام SuppliersCacheDataSource
ایجاد
کنید.
ObjectDataSource را
به گونه ای پیکربندی کنید که از
متدGetSuppliers()
کلاسStaticCache
استفاده
کند.
شکل5:پیکربندی
ObjectDataSource
جهت
کار با کلاس StaticCache
شکل6:استفاده
از متد GetSuppliers()
جهت
بازیابی دادهای cache
شده
ی supplier
پس
از اتمام این ویزارد,
VS به
طور خودکار برای هر فیلد داده در
SuppliersDataTable یک
Boundfield اضافه
می کند .markup
اعلانی
Gridview و
ObjectDataSource باید
به صورت زیر باشد:
|
|
شکل
7 صفحه
را هنگامی که در browser
دیده
می شود ,نشان
می دهد.
خروجی
باید مشابه داده های گرفته شده از کلاس
SuppliersBLL لایه
ی BLL باشد,
اما
استفاده از کلاس StaticCache
باعث
شده است تا داده های supplierرا
در آغاز application
, cache شده
بر گرداند.
می
توانید breakpoint
ی در
متد GetSuppliers()
کلاسStaticCache
جهت
بررسی این عملکرد قرار دهید.
شکل7:
داده
های cache
شده
ی supplier
در
GridView
نشان
داده شده است.
خلاصه
بیشتر
مدلهای داده شامل مجموعه ای از داده های
استاتیک هستند,
که
معمولا به فرم جداول مراجعه (lookup
tables) پیاده
سازی می شوند.
از
آنجا که این اطلاعات استاتیک هستند,
هیچ
دلیلی برای ادامه ی دسترسی به دیتابیس در
هر بار که این اطلاعات لازم است نمایش
داده شوند,
وجود
ندارد.
بعلاوه,
به دلیل
ماهیت استاتیک آنها,
وقتی
داده ها cache
می شوند
هیچ نیازی به انقضا و خاتمه نیست.
در این
مبحث دیدیم که چگونه داده ها را بگیریم و
آنها را در
data cache ,
cache کنیم.
اطلاعات
در آغاز یکapplication
, cache
شدند
و تا زمان حیات
application در
cache باقی
می مانند.
در
این مبحث و دو مبحث
قبل ,جهت
cache کردن
داده ها برای مدت حیات application
, از
منقضی شدن مبتنی بر زمان
استفاده کردیم.
جهت
کار با دیتابیس ها cache
کردن
مبتنی بر زمان ایده آل و خیلی کارا نیست.
Cache کردن
در صورتی بهینه وایده آل است که زمانی که
داده ها در لایه ی زیرین ویرایش شدند از
cache خاج
شوند .جهت
بکارگیری این تکنیک باید از SQL
cache dependencies استفاده
کنیم که موضوع مبحث بعدی است .
شاد
و موفق باشید
پاییز
86
نوشته شده توسط وحید نایینی
Script های مربوط به زمان
این ها script هایی هستند که مربوط به زمان هستند .
PageTimer("","")
ExitTimer("")
ScriptTimer("","")
RunScript("")
Pause("")
Return()
Refresh()
در آموزش های قبلی برخی از این کد ها استفاده کردیم اما در این بخش بیشتر به این script ها می پردازیم :
PageTimer("ms","PageLabel")
با اجرای این کد می توان پس از زمانی که تعیین می کنید به صفحه مورد نظر بروید . مثلا در این کد پس از گذشت 1000 میلی ثانیه (1 ثانیه) به صفحه ای که با Label آن را در قسمت دوم نوشته ایم (در اینجاpage 2 ) می رود :
PageTimer("1000","Page 2")
ExitTimer("ms")
این یک تایمر است که پس از گذشتن زمان مشخص شده پنجره بسته می شود (عمل Exit() انجام می شود) . در این کد پس از کذشتن یک دقیقه پس از اجرای این Script پنجره بسته خواهد شد .
ExitTimer("60000")
ScriptTimer("ObjectLabel","ms")
پس از گذشتن زمان تعیین شده Script مورد نظر اجرا می شود . در اینجا فقط منظور شئ Script نیست این کد مربوط به هر شئی که بتوان در آن Script مورد نظر خودتان را وارد کنید مثلا Text Button ، Rectangle و… می باشد . در قسمت اول نام شئ و در قسمت دوم زمان را می نویسیم . در مثال شئی با نام Script پس از 1 ثانیه اجرا می شود .
ScriptTimer("Script","1000")
RunScript("ObjectLabel")
این کد مانند کد بالا عمل می کند با این تفاوت که بلافاصله Script را اجرا می کند .
RunScript("Script")
Pause("ms")
می انید که برای اجرای کد ها ، آنها از بالا به پایین خوانده می شود (بدون هیچ وقفه ای) . از این دستور برای وقفه در بین خطوط کد ها استفاده می شود .
Return()
اگر خطوط Script ها را مانند یک رشته سیم فرض کنیم ، دستور Return مانند کلیدی است که این ارتباط و رسانایی بین رشته ها را قطع می کند . یا وقتی به این خط رسید بقیه خط ها را نمی خواند . از اینscript می توانید در دستور شرطی If یا حلقه for استفاده کنید .
Refresh()
تقریبا از اسم این کد می توان به طرز کار آن پی برد . این Script در حلقه ها بسیار مفید است . مثلا در یک حلقه Normal در هنگام شمارش شما نمی توانید از کلید های دیگر استفاده کند . اما اگر در حلقه خود Refresh را جای دهید این مشکل برطرطرف می شود .
برای اجرای کد های نمونه زیر ، یک Text با نام Counter ایجاد کنید .
یک حلقه با Refresh :
For n=1 To 100000
i=n
DisplayValue("Counter","i")
Refresh()
Next n
یک حلقه Normal :
For n=1 To 100000
i=n
DisplayValue("Counter","i")
Next n
تغییری که در اجرای این دو حلقه وجود دارد کاملا محسوس است .
جواب سوالها :
سوال 1 . تمرین N خط صفحه را به چند قسمت تقسیم می کند را طوری بنویسید که اگر عدد ورودی از 0 کمتر بود پیامی با این مضمون که "عدد را اشتباه وارد کرده اید ، دوباره تلاش کنید" ظاهر شود .
جواب : یک دستور شرطی If به آن اضافه می کنیم . دستور زیر مربوط به کلید است :
i=0
p=1
If (A>0) Then
For 1 To A
i=i+1
p=p+i
Next
DisplayValue("Answer","p")
Else
Message("The number is not correct , try again .","")
End
سوال 2 . ساعتی بسازید که ساعت ، دقیقه و ثانیه را وارد می کنیم و در همان زمانی که ما مشخص کردیم یک موسیقی پخش کند . (برای پخش موسیقی از این Action script استفاده کنید : AudioOpen("") ) .
جواب : اول یک ساعت با قرار دادن CBK_TimeHMS در Label متن (Text) مورد نظر بسازید . بعد 3 تا InputText درست می کنیم تا ساعت ، دقیقه و ثانیه مورد نظر را در آنها ثبت کنیم . در Properties آنها ، دکمه رادیویی Integer را انتخاب و نام های Hour ، Min و Sec را برای آن ها انتخاب کنید . حالا یک دکمه بسازید که در آن دستور یک Script به نام TimeSet را اجرا می کند . کار این Script این خواهد بود که زمان وارد شده در TextInput ها را با زمان فعلی مطابقت دهد . همچنین این Script باید هر ثانیه اجر شود تا بتواند زمان را تشخیص دهد . پس برای دکمه می نویسیم :
RunScript("TimeSet")
و برای < ;span style="font-family: Tahoma">Script می نویسیم :
H=CBK_Hour
M=CBK_Minute
S=CBK_Second
If (Hour=H) Then
If (Min=M) Then
If (Sec=S) Then
AudioOpen("E:\Musics\Mansour\The Fugitive.mp3")
End
End
End
ScriptTimer("TimeSet","1000")
در 3 خط اول ساعت ، دقیه و ثانیه را به 3 تا Integer نسبت میدهیم که در مراحل بعدی اسکریپت نویسی آسان تر باشد . دستور شرطی If هم در اینجا به این شکل کار می کند که اول ساعت را با ساعت کامپیوتر مقایسه می کند اگر مساوی بودند به سراغ دقیقه و پس از آن ثانیه می رود و اگر ثانیه هم درست بود دستور را اجرا می کند . در خط آخر هم پس از 1 ثانیه دوباره خودش را اجرا میکند .
سوال 3 . یک کلید بسازید که نام آن Play است . با کلیک کردن روی آن یک موسیقی پخش می شود و همچنین نام آن به Stop تغییر می کند که با کلیک کردن دو باره موسیقی قطع می شود . (برای قطع شدن موسیقی از این Action script استفاده کنید : AudioStop("") ) .
یک ترفندی که در اینجا می تونیم به کار ببریم این است که به هر کدام از حالت ها یک عدد نسبت دهیم مثلا یک عدد صحیح (Integer) تعریف می کنیم و برای حالت Play آن عدد 0 و برای حالت Stop عدد 1 را در نظر می گیریم . در اینجا نام عدد صحیح (Integer) ، play است . برای اینکه اولین بار که روی دکمه کلیک می کنید ، موسیقی پخش شود ، در قسمت Script مربوط به Properties صفحه ینویسید : play=0
نام دکمه را هم به Play تغییر دهید و این کد هارا در قسمت Script دکمه بنویسید :
If (play=0) Then
AudioOpen("e:\beethoven\moon shine.mp3")
AudioPlay()
name$=‘Stop‘
LoadText("TextBTN","name$")
play=1
Return()
End
If (play=1) Then
AudioStop()
name$=‘Play‘
LoadText("TextBTN","name$")
play=0
End
در اینجا فرض شده که موسیقی ای باز نشده پس اول موسیقی را باز می کنیم و سپس آن را Play می کنیم . اما اگر بخواهیم به جای STOP از Pause استفاده کنیم یعنی از این Script استفاده کنیم : AudioPause()، باز هم از اول موسیقی اجرا خواهد شد .برای رفع این مشکل می توانیم دستور AudioOpen را در قسمت Script صفحه قرار دهیم ، و بعد از آن دستور Stop را می آوریم تا فورا موسیقی Stop شود . به این شکل :
play=0
AudioOpen("e:\beethoven\moon shine.mp3")
AudioPause()
و در قسمت Script دکمه هم کد های زیر را می نوسیم :
If (play=0) Then
AudioPlay()
name$=‘Stop’
LoadText("TextBTN","name$")
play=1
Return()
End
If (play=1) Then
AudioPause()
name$=‘Play’
LoadText("TextBTN","name$")
play=0
End
سوال 4 . برنامه ای بسازید که مینیمم وماکزیمم بین دو عدد را به دست آورد و در دو خروجی مجزا (Text) نمایش دهد .
این نسبت به 3 تا قبلی آسون تره !
اول دو تا Text ایجاد کنید و نام آنها را Min و Max بگذارید. دو تا InputText هم بسازید ، آنها را به شکل Float تعریف کنید (در Properties قسمت Output گزینه Float را انتخاب کنید ) و نام آن ها (قسمت Output در Properties) را A1 و A2 بگذارید . یک دکمه هم بسازید و کد های زیر را در آن وارد کنید:
If (A1>A2) Then
DisplayValue("Max","A1")
DisplayValue("Min","A2")
End
If (A2>A1) Then
DisplayValue("Max","A2")
DisplayValue("Min","A1")
End
اما اگر هر دو مساوی باشند عددی برای نمایش در Min و Max نخواهد داشت . اگر این کد را وارد کنید در Min و Max می نویسد که دو عدد مساوی هستند .
If (A1>A2) Then
DisplayValue("Max","A1")
DisplayValue("Min","A2")
End
If (A2>A1) Then
DisplayValue("Max","A2")
DisplayValue("Min","A1")
End
If (A1=A2) Then
Equl$=CHAR(A1)+‘ = ‘+CHAR(A2)
DisplayValue("Max","Equl$")
DisplayValue("Min","Equl$")
End
سوال 5 . برنامه ای بسازید که با وارد کردن 3 عدد به عنوان 3 ضلع مثلث بگوید که این مثلث قائم الزاویه هست با نه ؟ (با استفاده از قضیه فیثاغورس)
برای ورودی 3 عدد 3 تا Text Input بسازید و برای خروجی آن حالت Integer و نام های A ،B و C بگذارید . می خواهیم برنامه را طبق قضیه فیثاغورس بنویسیم :
![]()
اول با دستور شرطی مینویسیم که آیا مجذور A مساوی مجذور B به اضافه C است یا نه . اگر مساوی بود که پیامی ظاهر می شود و می گوید که مثلث قائمه است ، اگر مساوی نبود می بیند که آیا مجذور B مساوی مجذور C به اضافه A است یا نه و به همین شکل ادامه پیدا می کند و اگر 3 ضلع توانایی ساخت مثلث قائمه را نداشتن با پیامی به ما هشدار می دهد .
یک کلید بسازید و این دستور ها را به آن بدهید :
Yes$=‘Yessss’
No$=‘No’
If (A^2=B^2+C^2) Then
Message("","Yes$")
Else
If (B^2=A^2+C^2) Then
Message("","Yes$")
Else
If (C^2=A^2+B^2) Then
Message("","Yes$")
Else
Message("","No$")
End
End
End
سوال 6 . یک برنامه که پنجره فرمت ویندوز را 100000 بار در ثانیه نشان دهد !
خیلی آسونه و البته زیاد نتیجه جالبی ندارد (می تونید امتحان کنید) حالا من 100 بار می زنم خودتون اگه خواستید 100000 بار بزنید (اما نزنین بهتره) .
For 1 To 100
Run("rundll32.exe","shell32.dll,SHFormatDrive")
Refresh()
Next
همون طور که میبینید بیشتر سوالها در مورد دستور If است و فقط 2 تا از اونها درباره For است . این قسمت چون می
خواستم به سوال ها جواب بدهم بخش آموزشی این مقاله کمتر شد (اما خود سوال ها هم آموزشی اند ) .
وحید نائینی
|
نویسنده: عبدالحمید انصاری نسب |
آشنایی با برنامه EES |
|
ناشر: www.dim-knight.blogfa.com |
|
|
توضیحات: آشنایی با برنامه EES
|
|
|
زبان: فارسی |
حجم کتاب: 250 کیلوبایت |
تعداد صفحات: 14 |
نوع فایل: PDF |
|
*** برای مطالعه این کتاب برنامه اجرا کننده آن را از این قسمت دانلود کنید. *** در صورت دانلود نشدن کتاب، بر روی Download راست کلیک کرده و گزینه …Save Target As را انتخاب نمایید. |
irpdf . com














