0

آموزش MVC

 
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

آموزش MVC

با عرض سلام 

از دوستان خواهشمندم سوالات  و آموزش های خود در مورد mvc را مطرح نمایید

دوشنبه 18 آبان 1394  1:09 PM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

چرا mvc ؟

چرا ASP.NET MVC ؟
 
با وجود فریم ورک پخته‌ای به نام ASP.NET web forms، اولین سؤالی که حین سوئیچ به ASP.NET MVC مطرح می‌شود این است: «برای چی؟». بنابراین تا به این سؤال پاسخ داده نشود، هر نوع بحث فنی در این مورد بی فایده است.
 
مزایای ASP.NET MVC نسبت به ASP.NET web forms
 
1) سادگی نوشتن آزمون‌های واحد
مهم‌ترین دلیل استفاده از ASP.NET MVC صرفنظر از تمام دلایل دیگر، بحث طراحی ویژه آن جهت ساده سازی تهیه آزمون‌های واحد است. مشکل اصلی نوشتن آزمون‌های واحد برای برنامه‌های ASP.NET web forms، درگیر شدن مستقیم با تمام جزئیات طول عمر یک صفحه است. به علاوه فایل‌های code behind هر چند به ظاهر کدهای منطق یک صفحه را از کدهای HTML مانند آن جدا می‌کنند اما در عمل حاوی ارجاعات مستقیمی به تک تک عناصر بصری موجود در صفحه هستند (حس غلط جدا سازی کدها از اجزای یک فرم). اگر قرار باشد برای این وب فرم‌ها و صفحات، آزمون واحد بنویسیم باید علاوه بر شبیه سازی چرخه طول عمر صفحه و همچنین رخدادهای رسیده، کار وهله سازی تک تک عناصر بصری را نیز عهده دار شویم. اینجا است که ASP.NET web forms گزینه‌ی مطلوبی برای این منظور نخواهد بود و اگر نوشتن آزمون واحد برای آن غیرممکن نباشد، به همین دلایل آنچنان مرسوم هم نیست.
البته شاید بپرسید که این مساله چه اهمیتی دارد؟ امکان نوشتن ساده‌تر آزمون‌های واحد مساوی است با امکان ساده‌تر اعمال تغییرات به یک پروژه بزرگ. تغییرات در پروژه‌های بزرگی که آزمون واحد ندارند واقعا مشکل است. یک قسمت را تغییر می‌دهید، 10 قسمت دیگر به هم می‌ریزند. اینجا است که مدام باید به کارفرما گفت: «نه!»، «نمیشه!» یا به عبارتی «نمی‌تونم پروژه رو جمع کنم!» چون نمی‌تونم سریع برآورد کنم که این تغییرات کدام قسمت‌ها را تحت تاثیر قرار می‌دهند، کجا به هم ریخت. من باید خودم سریع بتونم مشخص کنم با این تغییر جدید چه قسمت‌هایی به هم ریخته تا اینکه دو روز بعد زنگ بزنند: «باز جایی رو تغییر دادی، یکجای دیگر کار نمی‌کنه!»
 
2) دستیابی به کنترل بیشتر بر روی اجزای فریم ورک
در طراحی ASP.NET MVC همه‌جا interface ها قابل مشاهد هستند. همین مساله به معنای افزونه پذیری اکثر قطعات تشکیل دهنده ASP.NET MVC است؛ برخلاف ASP.NET web forms. برای مثال تابحال چندین view engine، routing engine و غیره توسط برنامه نویس‌های مستقل برای ASP.NET MVC طراحی شده‌اند که هیچکدام با ASP.NET web forms میسر نیست. برای مثال از view engine پیش فرض آن خوشتان نمی‌آید؟ عوضش کنید! سیستم اعتبار سنجی توکار آن‌را دوست ندارید؟ آن‌را با یک نمونه بهتر تعویض کنید و الی آخر ...
به علاوه طراحی بر اساس interface ها یک مزیت دیگر را هم به همراه دارد و آن هم ساده سازی mocking (تقلید) آن‌ها است جهت ساده سازی نوشتن آزمون‌های واحد.
 
3) سرعت بیشتر اجرا
ASP.NET MVC یک سری از قابلیت‌های ذاتی ASP.NET web forms را مانند ViewState حذف کرده است. اگر وب را جستجو کنید، برنامه نویس‌های ASP.NET web forms مدام از این مساله شکایت دارند و راه‌ حل‌های مختلفی را جهت حذف یا فشرده سازی آن ارائه می‌دهند. ViewState در ابتدای امر جهت شبیه سازی محیط دسکتاپ در وب درنظر گرفته شده بود و مهاجرت ساده‌تر برنامه نویس‌های VB6 به وب، اما واقعیت این است که اگر یک برنامه نویس ASP.NET web forms به اندازه آن توجهی نداشته باشد، ممکن است حجم آن در یک صفحه پیچیده تا 500 کیلوبایت یا بیشتر هم برسد. همین مساله بر روی سرعت دریافت و اجرا تاثیر گذار خواهد بود.
 
4) کنترل‌های ASP.NET web forms آنچنان آش دهن‌سوزی هم نیستند!
خوب، ViewState حذف شده، بنابراین اکثر کنترل‌های ASP.NET web forms هم کاربرد آنچنانی در ASP.NET MVC نخواهند داشت؛ اما واقعیت این است که اکثر اوقات اگر شروع به سفارشی سازی یک کنترل توکار ASP.NET web forms کنید تا مطابق نیازهای کاری شما رفتار کند، پس از مدتی به یک کنترل کاملا از نو بازنویسی شده خواهید رسید! بنابراین در ابتدای امر تا 80 درصد کار اینطور به نظر می‌رسد که به عجب سرعت بالایی در توسعه دست یافته‌ایم، اما هنگامیکه قرار است این 20 درصد پایانی را پر کنیم، به این نتیجه خواهیم رسید که این کنترل‌ها با این وضع ابتدایی که دارند قابل استفاده نیستند و نیاز به دستکاری قابل ملاحظه‌ای دارند تا نیازهای واقعی کاری را برآورده کنند.
 
5) کنترل کامل بر روی HTML نهایی تولیدی
اگر علاقمند به کار با jQuery باشید، مدام نیاز خواهید تا با ID کنترل‌ها و عناصر صفحه کار کنید. پیشتر ASP.NET web forms این ID را یک طرفه و به صورت مقدار منحصربفردی تولید می‌کرد که جهت کار با فریم ورک‌های جاوا اسکریپتی عموما مشکل ساز بود. البته ASP.NET web forms در نگارش‌های جدید خود مشکل عدم امکان مقدار دهی ClientId سفارشی را برای کنترل‌های وب خود برطرف کرده است و این مورد را می‌توان دستی هم تنظیم کرد ولی در کل باز هم آنچنان کنترلی رو خروجی HTML نهایی کنترل‌های تولیدی نیست مگر اینکه مانند مورد چهارم یاد شده یک کنترل را از صفر بازنویسی کنید!
همچنین اگر باز هم بیشتر با jQuery و ASP.NET web forms کار کرده باشید می‌دانید که jQuery آنچنان سنخیتی با ViewState و Postback وب فرم‌ها ندارد و همین مساله عموما مشکل‌زا است. علاوه بر آن اخیرا مایکروسافت توسعه ASP.NET Ajax خود را تقریبا در حالت تعلیق و واگذار شده به شرکت‌های ثالث درآورده است و توصیه آن‌ها استفاده از jQuery Ajax است. اینجا است که مدل ASP.NET MVC سازگاری کاملی را با jQuery Ajax دارد هم از لحاظ نبود ViewState و هم از جنبه‌ی کنترل کامل بر روی markup نهایی تولیدی.
یا برای مثال خروجی پیش فرض یک GridView، جدول HTML ایی است که این روزها همه‌جا علیه آن صحبت می‌شود. البته یک سری آداپتور CSS friendly برای اکثر این کنترل‌ها موجود است و ... باز هم دستکاری بیش از حد کنترل‌های پیش فرض جهت رسیدن به خروجی دلخواه. تمام این‌ها را در ASP.NET MVC می‌شود با معادل‌های بسیار باکیفیت افزونه‌های jQuery جایگزین کرد و از همه مهم‌تر چون ViewState و مفاهیمی مانند PostBack حذف شده، استفاده از این افزونه‌ها مشکل ساز نخواهد بود.
 
6) استفاده از امکانات جدید زبان‌های دات نتی
طراحی اصلی ASP.NET web forms مربوط است به دوران دات نت یک؛ زمانیکه نه Generics وجود داشت، نه LINQ و نه آنچنان مباحث TDD یا استفاده از ORMs متداول بود. برای مثال شاید ایجاد یک strongly typed web form الان کمی دور از ذهن به نظر برسد، زمانیکه اصل آن بر مبنای بکارگیری گسترده datatable و dataset بوده است (با توجه به امکانات زبان‌های دات نتی در آن دوران). بنابراین اگر علاقمند هستید که این امکانات جدید را بکاربگیرید، ASP.NET MVC برای استفاده از آن‌ها طراحی شده است!
 
7) از ASP.NET web forms ساده‌تر است
طراحی ASP.NET MVC بر اساس ایده Convention over configuration است. به این معنا که اجزای آن بر اساس یک سری قرار داد در کنار هم مشغول به کار هستند. مشخص است View باید کجا باشد، نام کنترلرها چگونه باید تعیین شوند و قرار داد مرتبط به آن چیست، مدل باید کجا قرار گیرد، قرار داد پردازش آدرس‌های صفحات سایت به چه نحوی است و الی آخر. خلاصه در بدو امر با یک فریم ورک حساب شده که شما را در مورد نحوه استفاده صحیح از آن راهنمایی می‌کند، مواجه هستید.
به همین ترتیب هر پروژه MVC دیگری را هم که مشاهده کنید، سریع می‌توانید تشخیص دهد قراردادهای بکارگرفته شده در آن چیست. بنابراین اگر قرار است ASP.NET را امروز شروع کنید و هیچ سابقه‌ای هم از وب فرم‌ها ندارید، یک راست با ASP.NET MVC شروع کنید. 
 
8) محدود به پیاده سازی مایکروسافت نیست
پیاده سازی‌های مستقلی هم از ASP.NET MVC توسط اشخاص و گروه‌های خارج از مایکروسافت وجود دارد: ^، ^، ^، ^ و ...
 
 
و در پایان یکی دیگر از دلایل سوئیچ به ASP.NET MVC ، «یاد گرفتن یک چیز جدید است» یا به عبارتی فرا گرفتن یک روش دیگر برای حل مسایل، هیچگاه ضرری را به همراه نخواهد داشت که هیچ، بلکه باعث بازتر شدن میدان دید نیز خواهد گردید.
 
 
یک دیدگاه دیگر
ASP.NET MVC برای شما مناسب نخواهد بود اگر ...
1) با پلی‌مرفیزم مشکل دارید.
ASP.NET MVC پر است از interfaces، abstract classes، virtual methods و امثال آن. بنابراین اگر تازه کار هستید، ابتدا باید مفاهیم شیءگرایی را تکمیل کنید.
 
2) اگر نمی‌توانید فریم ورک خودتون رو بر پایه ASP.NET MVC بنا کنید!
ASP.NET MVC برخلاف وب فرم‌ها به همراه آنچنان تعداد بالایی کنترل و افزونه از پیش مهیا شده نیست. در بدو امر شما فقط یک سری url helper، html helper و ajax helper ساده را خواهید دید؛ این نقطه ضعف ASP.NET MVC نیست. عمدا به این نحو طراحی شده است. همانطور که عنوان شد اکثر اجزای این فریم ورک قابل تعویض است. بنابراین دست شما را باز گذاشته است تا با پیاده سازی این اینترفیس‌ها، امکانات جدیدی را خلق کنید. البته پس از این چندین و چند سال که از ارائه آن می‌گذرد، به اندازه کافی افزونه برای ASP.NET MVC طراحی شده است که به هیچ عنوان احساس کمبود نکنید یا اینکه نیازی هم نداشته باشید تا آنچنان فریم ورک خاصی را بر پایه ASP.NET MVC تهیه کنید. برای مثال پروژهMvcContrib موجود است یا شرکت telerik یک مجموعه سورس باز کامل مخصوص ASP.NET MVC را ارائه داده است و الی آخر.
 
3) اگر نمی‌توانید از کتابخانه‌های سورس باز استفاده کنید.
همانطور که عنوان شد ASP.NET MVC به همراه کوهی از کنترل‌ها ارائه نشده است. اکثر افزونه‌های آن سورس باز هستند و کار با آن‌ها هم دنیای خاص خودش را دارد. چگونه باید کتابخانه‌های مناسب را پیدا کرد، کجا سؤال پرسید، کجا باگ گزارش داد، چگونه مشارکت کرد و غیره. خلاصه منتظر یک بسته شکیل حاضر و آماده نباید بود. خود ASP.NET MVC هم تحت مجوز MSPL به صورت سورس باز در دسترس است.
 
 
و یک نکته تکمیلی
مایکروسافت مدتی است شروع کرده به پرورش و زمزمه ایده «یک ASP.NET واحد». به عبارتی قصد دارند در یکی دو نگارش بعد، این دو (وب فرم و MVC) را یکی کنند. هم اکنون اگر مطالب وبلاگ‌ها را مطالعه کنید زیرساخت آن به نام ASP.NET Web API آماده شده است و در مرحله بتا است. نکته جالب اینجا است که این Web API امکان تعریف یکپارچه و مستقیم کنترلر‌های MVC را در وب فرم‌ها میسر می‌کند. ولی باز هم نام آن Controller است یعنی جزئی از ASP.NET MVC و کسی می‌تواند از آن استفاده کند که با MVC‌ مشکلی نداشته باشد. بنابراین یادگیری MVC هیچ ضرری نخواهد داشت و جای دوری نخواهد رفت!
دوشنبه 18 آبان 1394  1:13 PM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

چگونه تشخیص دهیم یک سایت با Asp.Net Mvc نوشته شده ؟

 چگونه تشخیص دهیم یک سایت با Asp.Net Mvc نوشته شده ؟ 
ابتدا افزونه Server Spy را نصب کنید . این افزونه می تواند وب سروری که مورد استفاده است را تشخیص دهد .اگر IIS بود یعنی سایت از یکی از مشتقات ASP و یا ASP.Net

چگونه تشخیص دهیم یک سایت با Asp.Net Mvc نوشته شده ؟

ابتدا افزونه Server Spy را نصب کنید . این افزونه می تواند وب سروری که مورد استفاده است را تشخیص دهد .اگر IIS بود یعنی سایت از یکی از مشتقات ASP و یا ASP.Net

استفاده می کند .اگر پسوند صفحات به asp.  ختم شده بود Asp کلاسیک دهه نود است . در غیر اینصورت یا Asp.Net Web Form و یا Asp.Net Mvc است .در این حالت به سورس یکی از صفحات مراجعه کرده اگر خبری از View State نبود یعنی Asp.Net Mvc است .

البته این روش در ۹۰ درصد موارد جواب خواهد داد ..می شود هدر ارسالی وب سرور کلا تغییر داد . یعنی ضررورتی ندارد سایت استفاده کننده از IIS حتما اعلام کند که از این وب سرور استفاده می کند .و یا در Asp.Net Web Form می شود با ترفند هایی View Sate را حذف کرد . ولی این روش ها همه گیر نیست و روش های شناسایی مطرح شده روی اکثر سایت ها جواب خواهد دادد.

دوشنبه 18 آبان 1394  1:15 PM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

بالا بردن سرعت در MVC

 در MVC امکان استفاده از چند View Engine به صورت همزمان وجود دارد و همچنین هربار که قرار است Viewایی رندر شود، از تمام این‌ها تا یافتن موتور مناسب نمایش View جاری کوئری می‌گیرد. بدیهی است هرچقدر تعداد موتورهای ثبت شده در اینجا بیشتر باشند، زمان بیشتری نیز برای یافتن موتور نمایشی مناسب صرف خواهد شد؛ خصوصا اگر موتور مناسب در آخر لیست ثبت شده باشد.

بالا بردن سرعت در MVC

در Asp.Net MVC به صورت خود کار دو Engin برای View ها فعال است Razor و ASPX و بعد از هر بار درخواست View در چندین مسیر دنبال View های مورد نظر میگرده

در تصویر بالا میبینید که در صورت درخواست متد index از کنترلر home دنبال View هایی با Engin مربوط ASPX هم میگرده که سرعت برنامه رو پایین میاره

حالا قصد داریم Engin مربوط به ASPX رو غیر فعال کنیم

وارد Global.asax شوید و در Application_Start دو خط کد زیر را اضافه کنید

1
2
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());

 

حالا تصویر زیر رو ببینید همانگونه که مشخص است دیگه دنبال View های با Engin Aspx نخواهد گشت

موفق و پیروز باشید

دوشنبه 18 آبان 1394  1:17 PM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

آموزش اجرای AutoComplete در MVC

آموزش اجرای AutoComplete در MVC

 
یک برنامه از نوع MVC بسازید سپس روی پوشه Model کلیک راست کرده و یک کلاس به نام Person بسازید:
1
2
public int PersonId { getset; }
       public string PersonName { getset; }

حالا رو یپوشه Controller کلیک راست کنید و گزینه Add سپس Controller را انتخاب کنید از لیست ظاهر شده Mvc 5 Controller With Views,Using Entity Framework را انتخاب کنید در پنجره Add Controller مدل خود را یعنی person را انتخاب کنید و بروی add کلیک کنید سپس برنامه را اجرا کنید و تعدادی نام به پروژه خود اضافه کنید سپس از منوی tools گزینه Nuget Package Manager و Manage Nuget Packages For Solution را انتخاب کنید و به قسمت آنلاین بروید و در سمت بالا سمت راست کلمه jQuery UI Autocomplete را جستجو کنید و( Jquery Ui (Combined Library را انتخاب و روی Install کلیک کنید و منتظر بمانید تا فایل های لازم به پروژه شما اضافه شود.سپس برنامه رو stop کنید به ویو Create بروید و فیلد PersonName را به شکل زیر تغییر دهید:

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="form-group">
    @Html.LabelFor(model => model.PersonName, new { @class "control-label col-md-2" })
    <div class="col-md-10">
        @Html.TextBoxFor(Model => Model.PersonName,
new
{
    @class "autocomplete-with-hidden",
    data_url = Url.Action("GetListForAutocomplete""People")
})
        @Html.HiddenFor(Model => Model.PersonId)
        @Html.ValidationMessageFor(model => model.PersonName)
    </div>
</div>

در انتهای ویو اسکریپت زیر را بنویسید:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
    $(function () {
        $('.autocomplete-with-hidden').autocomplete({
            minLength: 0,
            source: function (request, response) {
                var url = $(this.element).data('url');
 
                $.getJSON(url, { term: request.term }, function (data) {
                    response(data);
                })
            },
            select: function (event, ui) {
                $(event.target).next('input[type=hidden]').val(ui.item.id);
            },
            change: function (event, ui) {
                if (!ui.item) {
                    $(event.target).val('').next('input[type=hidden]').val('');
                }
            }
        });
    })
</script>

توسط اسکریپت بالا از طریق json به کنترلر رفته عمل جستجو را انجام داده و نتیجه از نوع json پاس داده میشود حال به Controller  خود رفته و یک تابع با فرمت json مینویسیم:

1
2
3
4
5
6
7
8
9
10
11
12
13
public JsonResult GetListForAutocomplete(string term)
       {
           Person[] matching = string.IsNullOrWhiteSpace(term) ?
               db.People.ToArray() :
               db.People.Where(p => p.PersonName.ToUpper().StartsWith(term.ToUpper())).ToArray();
 
           return Json(matching.Select(m => new
           {
               id = m.PersonId,
               value = m.PersonName,
               label = m.ToString()
           }), JsonRequestBehavior.AllowGet);
       }

حالا میتونید برنامه خود را اجرا کنید ودر ویوی Create  در هنکام تایپ نام AutoComplete عمل خواهد کرد.

دوشنبه 18 آبان 1394  1:19 PM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

ساخت یک برنامه ی تحت وب ASP.NET MVC 5

مقاله ی حاضر مبانی ساخت یک برنامه ی تحت وب MVC 5 را به وسیله ی محیط برنامه نویسی Visual Studio 2013 را به شما آموزش می دهد.

شروع به کار

کار خود را با نصب و راه اندازی Visual Studio Express 2013 for Web یا Visual Studio 2013 آغاز می کنیم.

Visual Studio یک محیط یکپارچه ی برنامه نویسی یا به اصطلاح IDE است. درست مانند زمانی که از Microsoft word برای نوشتن مطلب استفاده می کنید، از IDE هم به منظور ساخت برنامه های کاربردی یا Application ها استفاده می شود. در محیط Visual Studio و در قسمت بالایی آن یک نوار ابزار مشاهده می کنید که گزینه های مختلف در دسترس را برای شما نمایش می دهد. همچنین یک منو وجود دارد که از طریق آن می توان کارهای مورد نظر را به شیوه ای متفاوت انجام داد. به طور مثال بجای انتخاب گزینه ی  New Project از صفحه ی Start، می توان منو را باز کرده و گزینه های  File > New Project را انتخاب نمود.

clip_image002

ساخت اولین برنامه

روی New Project کلیک کرده، سپس Visual C# و به دنبال آن Web را از سمت چپ انتخاب کنید. حال می توانیدASP.NET  Web Application را انتخاب نمایید. پروژه ی خود را "MvcMovie" نام گذاری کرده، سپس OK را کلیک کنید.

clip_image004[6]

در پنجره ی محاوره ی New ASP.NET Project، روی MVC و سپس OK کلیک کنید.

clip_image006[6]

Visual Studio از یک قالب (template) پیش فرض برای پروژه ی ASP.NET MVC ای که ایجاد کردیم، استفاده کرده است. بنابراین شما هم اکنون یک برنامه ی آماده بدون انجام کوچکترین کاری در دست دارید! پروژه ای که هم اکنون مشاهده می کنید یک پروژه ی ساده ی "Hello World!" است و همچنین یک نقطه ی شروع مناسب برای ساخت برنامه می باشد.

clip_image008[6]

روی دکمه ی میانبر F5 کلیک کرده تا فرایند اشکال زدایی (debugging) آغاز شود. F5 باعث می شود محیط ویژوال استودیو IIS Express را راه اندازی کرده و برنامه ی شما را اجرا کند. ویژوال سپس مرورگر را اجرا کرده و home page برنامه را به نمایش می گذارد. همان طور که مشاهده می کنید نوار آدرس مرورگر localhost:port# را نشان می دهد و نه چیزی مانند example.com. این به این خاطر است که localhost همیشه به رایانه ی محلی شما اشاره می کند که در این مورد خاص همان برنامه ای را اجرا می کند که شما هم اکنون ایجاد کردید. هنگامی که ویژوال یک پروژه ی تحت وب را اجرا می کند، یک port تصادفی برای سرویس دهنده ی وب (web server) بکار می رود. در تصویر زیر شماره ی port، 1234 می باشد. زمانی که برنامه را اجرا می کنید، شماره ی port ای که به شما نمایش داده می شود متفاوت خواهد بود.

clip_image010

این برنامه به صورت پیش فرض گزینه ها و امکانایی همچون Home، Contact و صفحات About را ارائه می دهد. تصویر بالا لینک های Home، Contact و About را نمایش نمی دهد. بسته به اندازه ی پنجره ی مرورگر شما، ممکن است برای مشاهده ی لینک های مزبور لازم باشد، آیکون پیمایش (navigation) را کلیک کنید.

 

clip_image012[6]

clip_image014[4]

مرورگر همچنین امکان ثبت نام (register) و ثبت ورود (login) را فراهم می نماید. در گام بعدی با شیوه ی تغییر نحوه ی عملکرد برنامه آشنا شده و اطلاعات محدودی در رابطه با ASP.NET MVC کسب خواهید کرد. از برنامه ی ASP.NET MVCخارج شده تا با اصلاح مقداری کد برنامه را تغییر دهیم.

سه شنبه 19 آبان 1394  7:36 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

آموزش افزودن یک controller

آموزش افزودن یک controller

MVC سرواژه ی model-view-controller یا به فارسی مدل-نما-کنترلگر می باشد. MVC یک الگو ویژه ی طراحی و توسعه ی برنامه هایی است که به بهترین نحو تعبیه شده، قابل آزمایش می باشد و نگهداشت آن نیز بسیار سهل می باشد. در واقع MVC بر روی معماری های چند لایه ای جهت جداسازی قسمت های مختلف برنامه و به طور دقیق تر جدا کردن قسمت های منطقی برنامه از جمله داده ، مجوزها ، اعتبار سنجی داده ها و .... از لایه ی  Presentation یا در واقع همان لایه ای که مستقیم با کاربر  در ارتباط است ،قرار می گیرد. برنامه های تحت وب مبتنی بر MVC دربردارنده ی:

مدل: کلاس هایی که نشانگر داده ها و اطلاعات برنامه بوده و با استفاده از منطق اعتبارسنجی قوانین مربوط به لایه ی business را برای داده های برنامه اعمال می کند. در واقع بار اصلی معماری MVC بر عهده این بخش است . این بخش می تواند با داده ها در ارتباط باشد . منظور از داده لزوما ارتباط با بانک های اطلاعاتی مانند MSSQL ، Access و ... نیست ، حتی منبع داده ها در بخش Model می تواند یک آرایه از اعداد و یا هر چیز دیگری باشد . همان طور که گفته شد Model وظیفه ی بررسی اعتبار و درستی داده ها را هم بر دوش دارد.

نما: فایل های template که برنامه ی شما با استفاده از آن پاسخ های HTML را به صورت پویا ایجاد می کنند. این بخش که در واقع همان بخش Presentation Layer در معماری 3 لایه می باشد وظیفه ی بر قراری ارتباط با کاربر و دریافت داده از کاربر و نمایش داده های آماده با کاربر از طریق برقراری ارتباط با دو بخش دیگر یعنی Model وcontroller است. در حقیقت این بخش با داده های خام کار می کند.

کلاس هایی که درخواست های مرورگر را مدیریت می کند، داده ها را از بخش مدل بازیابی کرده، سپس قالب هایview که پاسخی به مرورگر باز می گرداند را مشخص می کند. همان طور که از اسم آن مشخص است controller یک بخش کنترل کننده می باشد و در واقع واسطی بین دو بخش Model و View محسوب می شود.

در مقاله ی آموزشی حاضر تمامی مفاهیم فوق را با جزئیات بیشتر برای شما شرح داده و نحوه ی استفاده از آن ها برای ساخت یک برنامه ی تحت وب را به شما آموزش می دهیم.

کار خود را با ایجاد یک کلاس controller آغاز می کنیم. در پنجره ی Solution  Explorer، روی پوشه ی Controllers راست کلیک کرده، سپس Add و پس از آن Controller را کلیک کنید.

clip_image002

در پنجره ی محاوره ی Add Scaffold، MVC 5  Controller – Empty را کلیک کرده، سپس Add را کلیک نمایید.

clip_image004

Controller خود را "HelloWorldController" نام گذاری کرده و Add را کلیک کنید:

clip_image006

مشاهده می کنید که در پنجره ی Solution  Explorer یک فایل جدید به نام HelloWorldController.cs و یک پوشه ی جدید به نام Views\HelloWorldایجاد شده است. controller در محیط برنامه نویسی ویژوال باز می باشد.

clip_image008

کد زیر را جایگزین محتویات فایل کنید.

using System.Web;

using System.Web.Mvc;

 

namespace MvcMovie.Controllers

{

public class HelloWorldController : Controller

{

//

// GET: /HelloWorld/

public string Index()

{

return "This is my <b>default</b> action...";

}

//

// GET: /HelloWorld/Welcome/

public string Welcome()

{

return "This is the Welcome action method...";

}

}

}

 

متدهای controller یک رشته ی HTML به عنوان نمونه برمی گردانند.Controller مربوطه HelloWorldController و اولین متد نیز Index نام گذاری شده است. حال آن را از یک مرورگر فراخوانی می کنیم. با زدن دکمه ی F5 یا Ctrl+F5به طور همزمان، برنامه را اجرا کنید. در مرورگر، "HelloWorld" را به path موجود در نوار آدرس ضمیمه کنید. صفحه ی برنامه ی مورد نظر ظاهری شبیه به تصویر زیر خواهد داشت. در متد بالا، کد مورد نظر یک رشته را به طور مستقیم برگرداند. شما به مرورگر دستور دادید مقداری HTML برگرداند و طبق درخواست شما مرورگر این کار را انجام داد.

clip_image010

بسته به URL دریافتی، ASP.NET MVC کلاس های controller متفاوت (و action method های مختلفی درون آن ها) را فرامی خواند. منطق مسیریابی پیش فرض URL که توسط ASP.NET MVC بکار برده می شود، از فرمت زیر برای تشخیص اینکه کدام کد باید فراخوانی شود، بهره می گیرد:

/[Controller]/[ActionName]/[Parameters]

فرمت مسیریابی را داخل فایل App_Start/RouteConfig.cs  تنظیم نمایید.

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

routes.MapRoute(

name: "Default",

url: "{controller}/{action}/{id}",

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

);

}

چنانچه برنامه را اجرا کرده ولی هیچ بخش URL ای برای آن فراهم نکرده باشید، در آن صورت URL به صورت پیش فرض بهcontroller  "Home" و متد action "Index" که در بخش defaults کد بالا تعریف کردید تنظیم می شود.

اولین بخش URL کلاس controller مورد نظر را برای اجرا مشخص می کند. بنابراین /HelloWorld بهHelloWorldController نگاشت (map) می شود. دوم ین بخش URL، آن متد action ای که باید روی کلاس اجرا شود را تعیین می کند. از این رو /HelloWorld/Index سبب می شود متد Index متعلق به کلاس HelloWorldControllerاجرا شود. تنها کاری که ما انجام دادیم  مراجعه به /HelloWorld بود و متد Index به صورت پیش فرض و بدون دخالت بکار برده شد. دلیلش این است که Index، یک متد پیش فرض است که در صورت تعریف نکردن یک متد (به صورت صریح)، بر روی controller فراخوانی می شود. سومین بخش URL (پارامترها) برای route data درنظر گرفته شده است. به آدرس http://localhost:xxxx/HelloWorld/Welcome مراجعه کنید. متد  Welcomeاجرا شده و رشته ی "This is the Welcome action method..." را برمی گرداند. Mapping (نگاشت) پیش فرض MVC/[Controller]/[ActionName]/[Parameters]  می باشد. Action method این URL، Welcome و controller آنHelloWorld می باشد. هنوز از بخش [Parameters] URL  استفاده نشده است.

clip_image012

حال مثال فوق را کمی تغییر داده تا بتوان مقداری اطلاعات پارامتر از URL به controller (به عنوان نمونه /HelloWorld/Welcome?name=Scott&numtimes=4) ارسال نمود. با اصلاح متد Welcome دو پارامتر مانند مثال زیر به آن ها اضافه کنید. توجه داشته باشید که کد مورد نظر با استفاده از امکان پارامتر اختیاری (optional-parameterC# مشخص می کند که پارامتر numTimes در صورت عدم ارسال مقدار برای پارامتر مورد نظر باید به صورت پیش فرض بر روی 1تنظیم گردد.

public string Welcome(string name, int numTimes = 1) {

return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes);

}

نکته ی امنیتی: کد بالا از HttpServerUtility.HtmlEncode برای محافظت از برنامه درمقابل ورودی مخرب (منظور جاوا اسکریپت) بهره می گیرد.

برنامه را اجرا کرده و به آدرس URL نمونه " http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numtimes=4 " مراجعه کنید. می توانید مقادیر مختلفی را برای name و numtimes در URL خود امتحان کنید. ASP.NET MVC model binding system به صورت خودکار پارامترهای نام گذاری شده را از query stringدر نوار آدرس به پارامترهای موجود در متد شما نگاشت می کند.

clip_image014

در نمونه ی بالا، بخش(parameters URL استفاده نشده است. پارامترهای name و numTimes به عنوان query string ارسال شده اند. علامت سوال " ? " که در URL فوق مشاهده می کنید، یک تفکیک کننده (separator) است که query string ها به دنبال آن می آیند. کاراکتر " & " نیز query string ها را از یکدیگر جدا می کند.

متد Welcome را با کد زیر جایگزین کنید:

public  string  Welcome (string name, int ID = 1)

{

return HttpUtility.HtmlEncode("Hello " + name + ", ID: " + ID);

}

برنامه را اجرا کرده و آدرس URL " http://localhost:xxx/HelloWorld/Welcome/3?name=Rick " را وارد نمایید.

clip_image016

این بار سومین بخش URL با ID پارامتر مسیریابی (route parametermatch شد (منطبق بود). Action method کهWelcome نام گذاری شده حاوی یک پارامتر (ID) است که با تعریف URL در متد RegisterRoutes مطابقت دارد (match شد).

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

name: "Default",

url: "{controller}/{action}/{id}",

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

);

}

در برنامه های تحت وب که توسط ASP.NET MVC طراحی می شوند، رایج است که پارامترها به صورت route data بهaction method ها ارسال شود (مانند کاری که ما با ID فوق انجام دادیم)، سپس آن ها را به صورت query stringپاس دهید. همچنین می توان برای ارسال همزمان پارامترهای name و numtimes به صورت route data در URL، یکroute اضافه کنید. کافی است route "Hello" را داخل فایل App_Start\RouteConfig.cs اضافه کنید:

public class RouteConfig

{

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

name: "Default",

url: "{controller}/{action}/{id}",

defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }

);

routes.MapRoute(

name: "Hello",

url: "{controller}/{action}/{name}/{id}"

);

}

}

برنامه را اجرا کرده و به آدرس " /localhost:XXX/HelloWorld/Welcome/Scott/3 " مراجعه کنید.

clip_image018

برای اغلب برنامه های MVC مسیر (route) پیش فرض مناسب می باشد. در فواصل آینده به نحوه ی ارسال داده به وسیله ی model binder خواهیم پرداخت که در آن دیگر نیازی به دستکاری مسیر (route) پیش فرض نیست. مثال هایی که در فصل بکار برده و تشریح شدند، وظایف مربوط به بخش های view و controller را انجام می دادند.Controller به طور مستقیم HTML را بازمی گرداند. به طور معمول رایج نیست که controller مسقیم HTML را بازگردانی نماید، به این خاطر که کار کد را بسیار سنگین می کند. بجای آن یک فایل قالب view مجزا ایجاد می کنیم که به ساخت پاسخ های HTML کمک می کند.

سه شنبه 19 آبان 1394  7:37 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

آموزش افزودن یک view

آموزش افزودن یک view

در این درس کلاس HelloWorldController را اصلاح کرده تا با استفاده از view template file ها، فرایند ایجاد و ارسال پاسخ های HTML به کاربر سمت سرویس گیرنده را به طور کامل کپسوله سازی کنیم.

در ابتدا با استفاده از Razor view engine یک template file جدید ایجاد می کنیم. view template های مبتنی بر موتورRazor دارای یک پسوند .cshtml هستند و یک روش بسیار موثر در عین حال ساده برای ایجاد خروجی های HTML با استفاده از C# فراهم می نماید. Razor تعداد کاراکترهای تایپی و کلیدهایی که باید به هنگام نوشتن  view templateفشار دهید را به طور قابل توجهی کاهش می دهد و همچنین تجربه ی کدنویسی روان و سریع را به ارمغان می آورد.   

در حال حاضر متد Index به همراه رشته یک پیام ارسال می کند که در کلاس controller، hard-code شده است. متدIndex را تغییر داده تا مانند نمونه کد زیر یک شی view برگرداند:

public ActionResult Index()

{

    return View();

}

 

متد Index که در مثال فوق مشاهده می کنید از یک template view برای ایجاد پاسخ HTML و ارسال آن به مرورگر استفاده می کند. متدهای controller همچون  Index(که از آن ها با نام action methods نیز یاد می شود) به طور معمول یک ActionResult (یا یک کلاس مشتق شده از ActionResult) برمی گردانند و نه نوع های اولیه (primitive types) مانند نوع رشته.

روی پوشه ی Views\HelloWorldراست کلیک کرده و Add را انتخاب کنید، سپس MVC 5 View Page  with (Layout Razor) را کلیک نمایید.

 

clip_image002[4]

 

در پنجره ی محاوره ی Specify Name for Item، Index را وارد کرده، سپس OK را کلیک نمایید.

clip_image004[4]

در پنجره ی محاوره ی Select a Layout Page، _Layout.cshtml پیش فرض را پذیرفته و  را کلیک کنید.

clip_image006[4]

در پنجره ی محاوره ی فوق، پوشه ی Views\Sharedدر قاب سمت چپ انتخاب شده است. اگر از قبل یک layout fileسفارشی در پوشه ی دیگر ایجاد کرده باشید، می توانید آن را انتخاب کنید. درباره ی layout file بعدا توضیح خواهیم داد. فایل MvcMovie\Views\HelloWorld\Index.cshtml ایجاد شد.

clip_image008[4]

اکنون نشانه گذاری های (markup) رنگی شده را اضافه کنید.

@{

    Layout = "~/Views/Shared/_Layout.cshtml";

}

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>Hello from our View Template!</p>

 

روی فایل Index.cshtml راست کلیک کرده و View in Browser را انتخاب کنید.

clip_image010[4]


همچنین می توانید روی فایل Index.cshtml راست کلیک کرده و View in Page Inspector را انتخاب نمایید.

یا به روشی دیگر، برنامه را اجرا کرده و به آدرس http://localhost:xxxx/HelloWorld (کنترلر HelloWorld) مراجعه نمایید. متد Index در controller کار زیادی انجام نمی داد بلکه صرفا دستور return View() را اجرا می کرد. دستور ذکر شده مشخص می کرد که متد موردنظر باید از یک template file برای ارائه ی پاسخ به مرورگر استفاده کند. به این خاطر که شما اسم view template file برای استفاده را به صورت صریح مشخص نکرده اید، ASP.NET MVC به صورت پیش فرض از view file  Index.cshtml در پوشه ی \Views\HelloWorld استفاده می کند. تصویر زیر رشته ی "Hello from our View Template!" که در view، hard-code شده را نمایش می دهد.

 

clip_image012[4]

عالیه نه! اما همان طور که در تصویر بالا مشاهده می کنید، نوار عنوان مرورگر متن  "Index My ASP.NET Appli" و لینک بزرگ در بالای صفحه متن "Application name" را نمایش می دهد. بسته به اینکه چقدر صفحه ی پنجره ی مرورگر را کوچک می کنید، ممکن است لازم باشد سه نوار را در سمت راست، بالای صفحه کلیک کنید تا لینک های Home، About،Contact، Register و Log in را مشاهده کنید.

تغییر دادن view ها و صفحات layout

در مرحله ی اول، بایستی لینک "Application name" واقع در قسمت بالای صفحه را تغییر دهید. آن متن بین تمامی صفحات مشترک بوده و در تمامی آن ها موجود می باشد، اما حقیقت این است که تنها در یک قسمت پروژه پیاده سازی شده و در عین حال در تمامی صفحات برنامه نمایش داده می شود. به پوشه ی /Views/Shared در پنجره ی Solution Explorer مراجعه کرده، سپس فایل _Layout.cshtml را باز کنید. فایل نام برده layout page نامیده شده و در پوشه ی مشترکی جای گذاری شده که تمامی دیگر صفحات می توانند از آن استفاده کنند.

clip_image014

Layout template ها به شما این امکان را می دهند که layout نگهدارنده ی HTML سایت خود را یک مکان واحد مشخص کرده و آن را در چندین صفحه داخل سایت خود اعمال نمایید. خط حاوی @RenderBody() را پیدا کنید. RenderBody یکplaceholder است که در آن تمامی صفحات مختص view که ایجاد کرده اید، گنجانده شده در layout page، نمایش داده می شوند (در واقع صفحه محتوا در این قسمت قرار می گیرد. Layout برای نمایش قالب و طرح هر صفحه در برنامه به کار می رود). برای مثال، اگر شما لینک About را انتخاب کنید، Views\Home\About.cshtmlداخل متد RenderBody،render می شود.

محتوایات المان title را تغییر دهید. ActionLink را در layout template از "Application name" به "MVC Movie" تغییر داده، سپس controller را از Home به Movies تغییر دهید. فایل layout به طور کامل در زیر نمایش داده شده است:

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>@ViewBag.Title - Movie App</title>

    @Styles.Render("~/Content/css")

    @Scripts.Render("~/bundles/modernizr")

</head>

<body>

    <div class="navbar navbar-inverse navbar-fixed-top">

        <div class="container">

            <div class="navbar-header">

                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                </button>

                @Html.ActionLink("MVC Movie", "Index", "Movies", null, new { @class = "navbar-brand" })

            </div>

            <div class="navbar-collapse collapse">

                <ul class="nav navbar-nav">

                    <li>@Html.ActionLink("Home", "Index", "Home")</li>

                    <li>@Html.ActionLink("About", "About", "Home")</li>

                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>

                </ul>

                @Html.Partial("_LoginPartial")

            </div>

        </div>

    </div>

    <div class="container body-content">

        @RenderBody()

        <hr />

        <footer>

            <p>© @DateTime.Now.Year - My ASP.NET Application</p>

        </footer>

    </div>

    @Scripts.Render("~/bundles/jquery")

    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)

</body>

</html>

پس از اجرای برنامه مشاهده خواهید کرد که متن "MVC Movie " را نشان می دهد. حال لینک About را کلیک کرده و ببینید که این صفحه نیز مانند صفحه ی قبل متن "MVC Movie" را نمایش می دهد. بنابراین می توان یکبار این تغییر را در layout template اعمال کرد و دید که چگونه این تغییر (عنوان جدید) در تمامی صفحات موجود در سایت منعکس می شود.

clip_image016[4]

هنگامی که برای اولین بار فایل Views\HelloWorld\Index.cshtm را ایجاد کردیم، کد زیر را دربرداشت:

@{

    Layout = "~/Views/Shared/_Layout.cshtml";

}

کد razor بالا، layout page را تعریف یا تنظیم می کند. فایل Views\_ViewStart.cshtmlرا بررسی کنید، خواهید دید که دربردارنده ی همان razor markup است. فایل Views\_ViewStart.cshtml، layout ای را تعریف می کند که مشترک بوده و مورد استفاده ی تمامی view ها می باشد، بنابراین می توانید توسط comment یا به روش معمولی آن کد را از فایل Views\HelloWorld\Index.cshtmlحذف کنید.

 

 

 

@*@{

        Layout = "~/Views/Shared/_Layout.cshtml";

    }*@

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>Hello from our View Template!</p>

 

می توانید با استفاده از خاصیت Layout، یک layout view متفاوت تنظیم کنید و یا آن را روی مقدار null تنظیم نمایید تا هیچ layout file ای مورد استفاده قرار نگیرد.

حال عنوان Index view را تغییر دهید.

MvcMovie\Views\HelloWorld\Index.cshtml را باز کنید. دو مکان برای ایجاد تغییر وجود دارد: اول، آن متنی که در عنوان مرورگر ظاهر می شود و دیگری در header دوم (المان <h2>). آن را تا حدی تغییر دهید که بتوانید تشخیص دهید کدام تکه از کد، کدام بخش از برنامه را تغییر داده است.

@{

    ViewBag.Title = "Movie List";

}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

 

برای مشخص کردن یک title یا عنوان برای صفحه، تکه کد بالا خاصیت Title شی ViewBag (که در view template فایل Index.cshtml قرار دارد) را با مقدار "Movie List" تنظیم می کنیم. دقت داشته باشید که layout template (Views\Shared\_Layout.cshtml ) مقدار موجود در تگ <title> را به عنوان بخشی از قسمت <head> صفحه ی HTMLکه قبلا مورد اصلاح قرار گرفته بود، استفاده می کند.

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>@ViewBag.Title - Movie App</title>

    @Styles.Render("~/Content/css")

    @Scripts.Render("~/bundles/modernizr")

</head>

با استفاده از  ViewBag، می توان به راحتی پارامترهای دیگری را بین view template و layout file خود رد و بدل (پاس داد) کرد.

حال برنامه را اجرا کنید. توجه داشته باشید که عنوان مرورگر، heading اصلی، heading دوم تغییر یافته اند. (در صورت مشاهده نکردن تغییر، نگران نباشید. ممکن است مرورگر شما محتوای حافظه نهان یا cache را خوانده و برای شما به نمایش بگذارد. با استفاده از میانبر Ctrl+F5، کاری کنید که پاسخ از سرور بارگذاری شود.) عنوان مرورگر توسطViewBag.Title که در view template (Index.cshtml) و همچنین  "- "Movie App که در داخل layout file اضافه کردید، ایجاد و تنظیم می شود.

همچنین دقت کنید که چگونه محتوای موجود در view template " Index.cshtml" با محتوای view template "_Layout.cshtml " ادغام شده و یک پاسخ HTML به مرورگر ارسال شده است. layout template به شما این امکان را می دهد تا به آسانی تغییراتی را وارد کنید که در تمامی صفحات برنامه اعمال می شوند.

clip_image018[4]

اما باید توجه داشته باشید که داده های ما (در این مورد پیغام "Hello from our View Template!" ) hard-code شده هستند. برنامه ی MVC حاضر یک بخش به نام view یا نما و یک بخش به نام controller یا کنترلگر دارد، اما در آن خبری از یک model نیست. در مبحث بعدی نحوه ی ایجاد یک پایگاه داده و واکشی اطلاعات مدل از آن پایگاه داده را برای شما شرح می دهیم.

ارسال داده ها از controller به view

پیش از پرداختن به پایگاه داده و بحث درباره ی model ها، لازم است نحوه ی ارسال اطلاعات از controller به  view را تشریح کنیم. کلاس های controller در پاسخ به درخواست URL دریافتی فراخوانده می شوند.  کلاس controller جایی است که در آن کدهایی می نویسید که درخواست های مرورگر را مدیریت می کند ، داده از بانک اطلاعاتی واکشی کرده و در نهایت تصمیم می گیرد چه نوع پاسخی به مرورگر بازگرداند. در پی آن view template ها می توانند از یک controllerبکار گرفته شده و پاسخ مناسب HTML به مرورگر را ایجاد و قالب بندی (format) کنند.

Controller ها مسئول فراهم نمودن تمامی داده ها و اشیا لازم که view template برای ارائه ی خروجی به مرورگر به آن ها نیاز دارد، می باشد (  Controller قسمتی از برنامه است که تعامل با کاربر را مدیریت می کند.نوعا controller داده ها را از یک view می خواند، ورودی کاربر را کنترل می کند، و داده های ورودی را به model می فرستد). یک نکته ی بسیار مهم: یک view template هیچگاه نباید منطق business اجرا کند یا با پایگاه داده به طور مستقیم تعامل داشته باشد، بلکه یک view template صرفا باید با داده هایی که توسط controller در اختیار آن قرار گرفته، سروکار داشته باشد. دنبال کردن این رویکرد " جداسازی وظایف/separation of concerns " به شما در مرتب نگه داشتن کد و حفظ قابلیت آزمایش پذیری (testable) آن کمک شایانی می کند.

در حال حاضر، action method موجود در کلاس HelloWorldController که Welcome نام گذاری شده، یک پارامتر nameو numTimes می پذیرد، سپس مقادیر را به طور مستقیم به مرورگر (به صورت خروجی) تحویل (output) می دهد. به جای اینکه کاری کنیم تا controller این خروجی یا پاسخ را به صورت رشته ارائه دهد (render کند)، controller را گونه ای تغییر می دهیم که از یک template view استفاده کند. view template یک پاسخ پویا (dynamic response) ارائه می کند، بدین معنا که شما باید فقط دادهای مورد نیاز و مناسب را از controller به view ارسال نمایید تا بدین وسیله پاسخ و خروجی مناسب ایجاد شود. برای این منظور می توان کاری کرد که controller داده های پویایی (پارامترها) کهview template  به آن ها نیاز دارد را داخل یک شی ViewBag جای گذاری کند. پس از انجام این کار، view template می تواند به راحتی به آن داده های پویا از داخل شی ViewBag دسترسی داشته باشد.

به فایل HelloWorldController.cs بازگشته و متد Welcome را اصلاح کنید تا بتوان مقادیر Message و NumTimes را به شی ViewBag افزود. ViewBag یک شی پویا (dynamic object) است، بدین معنا که می توان هر چیزی که دلخواه تان است را داخل آن قرار دهید؛ ViewBag تا زمانی که چیزی درون آن قرار نداده اید، هیچ خاصیت تعریف شده ای نخواهد داشت.  ASP.NET MVC model binding system به صورت خودکار پارامترهای نامگذاری شده (name و numTimes) را ازquery string در نوار آدرس به پارامترهای موجود در متد نگاشت می کند. فایل کامل HelloWorldController.cs بدین شکل است:

    using System.Web;

     using System.Web.Mvc;

 

namespace MvcMovie.Controllers

{

    public class HelloWorldController : Controller

    {

        public ActionResult Index()

        {

            return View();

        }

        public ActionResult Welcome(string name, int numTimes = 1)

        {

            ViewBag.Message = "Hello " + name;

            ViewBag.NumTimes = numTimes;

            return View();

        }

    }

}

اکنون شی ViewBag دربردارنده ی داده هایی است که به صورت خودکار به view ارسال می شوند. در مرحله ی بعد به یک view template به نام welcome نیاز دارید! در منو Build، Build Solution را انتخاب کرده (و یا دکمه هایCtrl+Shift+B را به طور همزمان فشار دهید) تا پروژه ترجمه/کامپایل شود. روی پوشه ی Views\HelloWorld راست کلیک کرده و Add را کلیک نمایید. حال گزینه ی click MVC 5 View Page with (Layout Razor) را انتخاب نمایید.

clip_image019

 

در پنجره ی محاوره ی Specify Name for Item، Welcomeرا وارد کرده، سپس OK را کلیک کنید.

در پنجره ی محاوره ی Select a Layout Page، _Layout.cshtml پیش فرض را پذیرفته و OK را کلیک کنید.

clip_image020


فایل MvcMovie\Views\HelloWorld\Welcome.cshtml ایجاد شد.

Markup موجود در فایل Welcome.cshtml را جایگزین کنید. یک حلقه ایجاد می کنیم که رشته ی "Hello" را به تعداد دفعات مشخص شده از طرف کاربر تکرار کند. فایل کامل  Welcome.cshtml در زیر به نمایش گذاشته شده است:

@{

    ViewBag.Title = "Welcome";

}

<h2>Welcome</h2>

<ul>

    @for (int i = 0; i < ViewBag.NumTimes; i++)

    {

        <li>@ViewBag.Message</li>

    }

</ul>

برنامه را اجرا کرده و به آدرس زیر مراجعه کنید:

http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4

اکنون داده ها از URL دریافت شده و از طریق model binder به controller ارسال می گردد. Controller داده های مورد نظر را در شی ViewBag به صورت پکیج درآورده، سپس آن شی را به view پاس می دهد. View نیز داده ها را در قالبHTML به کاربر نمایش می دهد.

clip_image022

 

در نمونه ی فوق، با استفاده از یک شی ViewBag، اطلاعات را از controller  به view ارسال کردیم. در فواصل بعدی آموزش حاضر، از یک view model برای ارسال اطلاعات از controller به view استفاده می کنیم. این رویکرد (ارسال داده ازcontroller به view) ارسال اطلاعات، در مقایسه با روش قبلی از محبوبیت بیشتری برخوردار است.

در این درس یک مدل ایجاد کردیم، ولی ساخت پایگاه داده را در مبحث بعدی مطرح خواهیم کرد. در درس بعدی با استفاده از دانش کسب شده، یک پایگاه داده از فیلم ها ایجاد می کنیم.

سه شنبه 19 آبان 1394  7:39 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

افزودن یک Model

افزودن یک Model

در این مبحث به منظور مدیریت فیلم ها در پایگاه داده، تعدادی کلاس اضافه می کنیم. کلاس هایی که قرار است در این درس اضافه کنیم، بخش " model " برنامه ی تحت وب MVC محسوب می شود.

در این درس از یک تکنولوژی .NET به نام Entity Framework برای تعریف و کار با این کلاس های model بهره می گیریم. تکنولوژی مزبور که گاهی از آن به عنوان EF نیز یاد می شود، یک الگوی توسعه (development paradigm) به نام CodeFirst را پشتیبانی می کند. Code First به شما این امکان را می دهد که با نوشتن چند کلاس ساده، model object (اشیا مربوط به بخش model) ایجاد کنید. (این کلاس های ساده تحت عنوان کلاس های  poccoنیز شناخته می شوند.) سپس می توانید کاری کنید که پایگاه داده حین اجرا (on the fly) از کلاس های نام برده ساخته شوند که در نتیجه فرایند یا گردش کار توسعه را تسریع بخشیده و تجربه ی روانی را برای برنامه نویس به ارمغان می آورد. چنانچه لازم است اول پایگاه داده را ایجاد کنید، باز هم می توانید این آموزش را دنبال کرده و طی آن نحوه ی برنامه نویسی با بهره گیری از الگوی MVC و فن آوری EF را یاد بگیرید.

افزودن کلاس های Model

در پنجره ی Solution Explorer، روی پوشه ی Models راست کلیک کرده، Add را انتخاب کنید، سپس Class را کلیک نمایید.

clip_image002

"Movie" را به عنوان نام کلاس وارد نمایید.

حال پنج خاصیت (property) زیر را به کلاس Movie اضافه کنید:

using System;

 

namespace MvcMovie.Models

{

    public class Movie

    {

        public int ID { get; set; }

        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        public string Genre { get; set; }

        public decimal Price { get; set; }

    }

}

با استفاده از کلاس Movie، فیلم ها را در پایگاه داده نمایش می دهیم. هر نمونه ی شی Movie، برابر با یک  سطر در جدول پایگاه داده خواهد بود، و هر خاصیت (property) کلاس Movie به یک ستون در داخل جدول نگاشت می شود.

در همان فایل، کلاس MovieDBContext زیر را اضافه کنید:

using System;

using System.Data.Entity;

 

namespace MvcMovie.Models

{

    public class Movie

    {

        public int ID { get; set; }

        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        public string Genre { get; set; }

        public decimal Price { get; set; }

    }

    public class MovieDBContext : DbContext

    {

        public DbSet<Movie> Movies { get; set; }

    }

}

کلاس MovieDBContext نمایشگر بستر اجرای پایگاه داده ی movie در  Entity Frameworkبوده، که عملیات واکشی (fetching)، ذخیره سازی و بروز رسانی نمونه های کلاس movie داخل پایگاه داده را بر عهده دارد. MovieDBContext از کلاس پایه ی DbContext مشتق شده که توسط Entity Framework ارائه می شود.

برای اینکه بتوان به DbContext و DbSet اشاره کرد، بایستی دستور using را به اول فایل اضافه کنید:

using System.Data.Entity;

می توان این کار را به صورت دستی با افزودن دستور using انجام داد. یا با روشی دیگر می توانید بر روی خط های پرپیچ و خم قرمز رنگ راست کلیک کرده، Resolve را کلیک نمود، سپس using System.Data.Entity را انتخاب کرد.

clip_image004

 

توجه: چندین دستور using که بلا استفاده بودند حذف شده اند. می توان این کار را با راست کلیک کردن داخل فایل ،انتخاب Organize Usings و به دنبال آن کلیک بر روی Remove Unused Usings انجام داد.

 

clip_image006

 

پروسه ی افزودن model به پایان رسید. در درس بعدی با connection string های پایگاه داده و نحوه ی کار با آن ها آشنا خواهید شد.

سه شنبه 19 آبان 1394  7:40 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

ایجاد کردن یک connection string و کار با نسخه ی SQL Server LocalDB

 

ایجاد کردن یک connection string و کار با نسخه ی  SQL Server LocalDB

کلاس MovieDBContext که ایجاد کردید، وظیفه ی اتصال به پایگاه داده و نگاشت اشیا movie به سطر (رکورد) های پایگاه داده را بر عهده دارد. یکی از سوال هایی که ممکن است برای شما پیش آید این است که چگونه می توان تعیین کرد به کدام پایگاه داده متصل شود. در پاسخ باید گفت که نیازی نیست مشخص کنید کدام پایگاه داده مورد استفاده قرار گیرد، EF خود به صورت پیش فرض به پایگاه داده ی LocalDB متصل می شود. در این بخش به صورت صریح یکconnection string در فایل Web.config برنامه خود اضافه می کنیم.

SQL Server Express LocalDB

LocalDB یک نسخه ی سبک وزن و کم حجم از موتور پایگاه داده ی SQL Server Express است که به مجرد تقاضا راه اندازی شده و در حالت user mode اجرا می شود. LocalDB در یک حالت اجرایی ویژه ی SQL Server Express اجرا می شود که به شما اجازه می دهد با پایگاه داده به صورت فایل های mdf. کار کنید. به طور معمول، فایل های پایگاه داده ی LocalDB در پوشه ی App_Data پروژه ی وب نگه داری می شود.

SQL Server Express به هیچ وجه برای استفاده در برنامه های تحت وب تولیدی (production web applications) توصیه نمی شود. این امر به خصوص درمورد LocalDB صدق می کند؛ به هیچ وجه نباید LocalDB برای تولید با یک برنامه ی تحت وب بکار رود زیرا این نسخه اساسا برای کار با IIS (سرویس های اطلاعات اینترنتی) طراحی نشده است. با این حال، یک پایگاه داده ی LocalDB را می توان به راحتی به SQL Server یا SQL Azure انتقال migrate) )داد.

در ویرایش های 2012 و 2013 محیط برنامه نویسی Visual Studio، LocalDB به صورت پیش فرض همراه با خود Visual Studio نصب می شود.

به صورت پیش فرض، Entity Framework به دنبال یک connection string که دارای اسمی یکسان با کلاس object context (برای این پروژه ی خاص MovieDBContext) می باشد، می گردد.

فایل Web.config که در زیر به نمایش گذاشته شده را باز کنید. (منظور آن فایل Web.config که در پوشه ی  Viewsقرار دارد نیست.)

 

clip_image002

 

المان <connectionStrings> را پیدا کنید:

 

clip_image004

Connection string زیر را به المان داخل Web.config اضافه نمایید:

    <add name="MovieDBContext"

   connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True"

   providerName="System.Data.SqlClient"

/>

مثال زیر بخشی از فایل Web.config را نشان می دهد که connection string جدید به آن اضافه شده است:

  <connectionStrings>

      <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MvcMovie-20130603030321.mdf;Initial Catalog=aspnet-MvcMovie-20130603030321;Integrated Security=True" providerName="System.Data.SqlClient"/>

      <add name="MovieDBContext"    connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Movies.mdf;Integrated Security=True" providerName="System.Data.SqlClient"

/>

    connectionStrings>

 

دو connection string بسیار شبیه هستند. اولین connection string، DefaultConnection نامیده شده و برای مدیریت عضویت در پایگاه داده و اینکه چه کسی می تواند به برنامه (membership database) دسترسی داشته باشد، بکار می رود. Connection string ای که شما اضافه کرده اید یک پایگاه داده LocalDB به نام Movie.mdf تعریف می کند که در پوشه ی App_Data قرار می گیرد.

اسم connection string باید با اسم کلاس DbContext مطابقت داشته باشد.

using System;

using System.Data.Entity;

namespace MvcMovie.Models

{

    public class Movie

    {

        public int ID { get; set; }

        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        public string Genre { get; set; }

        public decimal Price { get; set; }

    }

    public class MovieDBContext : DbContext

    {

        public DbSet<Movie> Movies { get; set; }

    }

}

در واقع نیازی به افزودن connection string، MovieDBContext نیست. در صورت مشخص نکردن connection string،EF خود یک پایگاه داده ی LocalDB به همراه اسم کامل کلاس DbContext (در این موردMvcMovie.Models.MovieDBContext) در پوشه ی users ایجاد می کند. می توانید اسم پایگاه داده را مطابق میل خود انتخاب کنید مادام اینکه دارای پسوند .MDF باشد. به عنوان مثال می توان اسم پایگاه داده ی مورد نظر راMyFilms.mdf انتخاب کرد.

سه شنبه 19 آبان 1394  7:40 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

افزودن قابلیت جستجو

افزودن قابلیت جستجو

در این فصل از مقاله ی آموزشی MVC، نحوه ی افزودن قابلیت Search به متد Index را برای جستجوی movie ها بر اساس ژانر و اسم آن فیلم، شرح خواهیم داد.

بروز رسانی فرم Index

متد Index موجود در کلاس MoviesController را به صورت زیر ویرایش کنید:

 public ActionResult Index(string searchString)

{          

    var movies = from m in db.Movies

                 select m;

 

    if (!String.IsNullOrEmpty(searchString))

    {

        movies = movies.Where(s => s.Title.Contains(searchString));

    }

 

    return View(movies);

}

اولین خط متد Index، برای انتخاب movie ها یک LINQ query ایجاد می کند:

var movies = from m in db.Movies

                 select m;

}

 

Query در این برهه از زمان تعریف شده، اما هنوز بر روی پایگاه داده اجرا نشده است.

چنانچه پارامتر searchString دربردارنده ی یک رشته باشد، کوئری movie به گونه ای اصلاح می شود که مقدار search string با استفاده از کد زیر فیلتر شود:

if (!String.IsNullOrEmpty(searchString))

    {

        movies = movies.Where(s => s.Title.Contains(searchString));

    }

قسمت s => s.Title کد بالا، یک عبارت  Lambda است. عبارت های Lambda در LINQ query های مبتنی بر متد، به عنوان آرگومان برای متدهای query operator (مانند تابع where که در مثال فوق بکار گرفته شده) استفاده می شوند. LINQ query ها به محض تعریف شدن یا در زمانی که به واسطه ی فراخوانی یک متد همانند Where یا OrderBy مورد دستکاری قرار می گیرند ، اجرا نمی شود. بلکه اجرای query به تعویق می افتد، بدین معنا که ارزیابی عبارت تا زمانی که متد ToList فراخوانی نشده یا مقدار داخل حلقه نیافتاده و تکرار نشده به تاخیر افتاده و صورت نمی گیرد. در نمونه یSearch، query در Index.cshtml view اجرا می شود.

توجه: متد Contains روی پایگاه داده اجرا شده، نه بر روی کد c# مثال بالا. در پایگاه داده، متد نام برده به SQL LIKEکه به کوچک و بزرگی حروف حساس است، نگاشت می شود.

اکنون شما می توانید Index view را که فرم را به کاربر نمایش می دهد، بروز رسانی کنید.

برنامه را اجرا کرده و به /Movies/Index پیمایش کنید. یک query string مانند این نمونه ?searchString=ghost بهURL ضمیمه کنید. Movie های فیلتر شده نمایش داده می شوند.

clip_image002[4]

اگر  پارامتر ورودی متد Index را متغیری به نام id تغییر دهیم، پارامتر id با placeholder {id} برای مسیرهای تنظیم شده در فایل App_Start\RouteConfig.cs منطبق (match) می شود.

{controller}/{action}/{id}

متد Index اصلاح نشده:

        public ActionResult Index(string searchString)

        {

            var movies = from m in db.Movies

                         select m;

            if (!String.IsNullOrEmpty(searchString))

            {

                movies = movies.Where(s => s.Title.Contains(searchString));

            }

            return View(movies);

        }

متد Index اصلاح شده:

public ActionResult Index(string id)

        {

            string searchString = id;

            var movies = from m in db.Movies

                         select m;

            if (!String.IsNullOrEmpty(searchString))

            {

                movies = movies.Where(s => s.Title.Contains(searchString));

            }

            return View(movies);

        }

حال می توانید search title را بجای اینکه به عنوان مقدار query string ارسال کنید، آن را به صورت route data (یک بخش از URL) پاس دهید.

 

clip_image004[4]

 

اما شما نمی توانید انتظار داشته باشید که کاربران هر بار برای جستجو به دنبال یک فیلم، URL را تغییر دهند. بنابراین شما با افزودن UI به کاربر کمک می کنید فیلم ها را فیلتر کند. اگر ورودی متد Index را برای تست اینکه پارامتر ID، route-bound چگونه ارسال می شود، تغییر داده اید، بایستی آن را به حالت قبلی برگردانید تا متد Index یک پارامتر به نام searchString بپذیرد:

   public ActionResult Index(string searchString)

        {

            var movies = from m in db.Movies

                         select m;

            if (!String.IsNullOrEmpty(searchString))

            {

                movies = movies.Where(s => s.Title.Contains(searchString));

            }

            return View(movies);

        }

 

فایل Views\Movies\Index.cshtml را باز کرده و درست بعد از Views\Movies\Index.cshtml، form markup رنگی شده ی زیر را اضافه کنید:

@model IEnumerable<MvcMovie.Models.Movie>

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>

    @Html.ActionLink("Create New", "Create")

 

    @using (Html.BeginForm())

    {

    <p>

        Title: @Html.TextBox("SearchString") <br />

        <input type="submit" value="Filter" />

    </p>

    }

    </p>

 

Html.BeginForm یک تگ باز <form>  ایجاد می کند. Html.BeginForm باعث می شود هنگامی که کاربر فرم را با کلیک بر روی دکمه ی Filter ارسال (submit) می کند، اطلاعات را به خودش post کند.

Visual Studio 2013  یک قابلیت ویژه برای نمایش و ویرایش فایل های view دارد. هنگامی که یک برنامه را اجرا می کنید در حالی که فایل view باز است، Visual Studio 2013، controller action method مناسب را برای نمایش view، صدا می زند.

clip_image006[4]

 

Index view را در محیط Visual Studio باز کرده، کلیدهای Ctr +F5 یا F5 را برای اجرای برنامه فشار دهید، سپس movieمورد نظر را سرچ کنید.

 

clip_image008[4]

هیچ نسخه ی overload شده ای از خصیصه ی HttpPost متد Index وجود ندارد، به آن نیازی هم ندارید زیرا که متد وضعیت برنامه (application state) را تغییر نمی دهد، بلکه فقط داده ها را فیلتر می کند.

می توانستید متد HttpPost Index را اضافه کنید. در آن صورت، فراخواننده ی تابع (action invoker) با متد HttpPost Index منطبق (match) می شد و متد HttpPost Index به صورتی که در تصویر زیر نمایش داده شده، اجرا می شد:

 

        [HttpPost]

public string Index(FormCollection fc, string searchString)

{

    return "<h3> From [HttpPost]Index: " + searchString + "</h3>";

}

 

clip_image010[4]

 

با این وجود، اگرهم این نسخه ی HttpPost متد Index را اضافه می کردید، بازهم در (نحوه ی) پیاده سازی محدودیتی وجود دارد. فرض کنید می خواهید یک search به خصوص را bookmark کنید یا یک لینک را به دوستان خود ارسال کنید تا با کلیک روی آن همان فهرست فیلتر شده از movie ها را مشاهده کنند. دقت داشته باشید که آدرس درخواست HTTP POST با آدرس درخواست GET (localhost:xxxxx/Movies/Index) یکی می باشد – در خود URL هیچ اطلاعات جستجویی وجود ندارد. در حال حاضر، اطلاعات search string به صورت یک مقدار form field به سرور ارسال شده است، بدین معنا که شما نمی توانید آن اطلاعات جستجو را برای bookmark کردن یا ارسال به دوستان در یک URL ضبط (capture) کنید.

راه حل، استفاده از یک نسخه ی overload شده ی متد BeginForm است که مشخص می کند درخواست POST باید اطلاعات جستجو را به URL اضافه کند و اینکه باید به نسخه ی HttpGet متد Index هدایت شود. Markup زیر را جایگزین متد بدون پارامتر BeginForm کنید:

@using (Html.BeginForm("Index","Movies",FormMethod.Get))

clip_image012[4]

 

حال زمانی که یک جستجو را انجام و به سرور ارسال می کنیم، یک query string به URL اضافه می شود. جستجو همچنین به متد HttpGet Index فرستاده می شود، حتی اگرهم یک متد HttpPost Index از قبل داشته باشید.

 

clip_image014[4]

 

افزودن Search بر اساس Genre

اگر نسخه ی HttpPost متد Index را اضافه کرده بودید، اکنون آن را حذف کنید.

در این بخش یک ابزار یا قابلیت اضافه می کنید که به کاربران اجازه می دهد بر اساس Genre در میان movie ها جستجو انجام دهند. برای این منظور متد Index را با کد زیر جایگزین کنید:

public ActionResult Index(string movieGenre, string searchString)

{

    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies

                   orderby d.Genre

                   select d.Genre;

    GenreLst.AddRange(GenreQry.Distinct());

    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies

                 select m;

    if (!String.IsNullOrEmpty(searchString))

    {

        movies = movies.Where(s => s.Title.Contains(searchString));

    }

    if (!string.IsNullOrEmpty(movieGenre))

    {

        movies = movies.Where(x => x.Genre == movieGenre);

    }

    return View(movies);

}

 

این نسخه ی متد Index یک پارامتر اضافی می گیرد، که آن پارامتر movieGenre می باشد. اولین خطوط کد، یک شی Listبرای نگه داشتن movie genre ها از پایگاه داده ایجاد می کنند.

کد زیر یک LINQ query است که تمامی genre ها را از پایگاه داده بازیابی می کند.

            var GenreQry = from d in db.Movies

                           orderby d.Genre

                           select d.Genre;

کد با استفاده از متد AddRange مجموعه ی ژنریک List، تمامی genre های مجزا و متمایز (distinct) را به لیست اضافه می کند. (بدون تعریف کننده ی Distinct، genre های تکراری اضافه می شد، برای مثال ژانر comedy دوبار به نمونه ی مورد نظر ما افزوده می شد). کد مورد نظر سپس فهرستی از genre ها را در شی ViewBag.movieGenre ذخیره می کند. برنامه های نوشته شده با MVC، معمولا داده های دسته بندی مانند ژانر یک فیلم را به صورت یک شی SelectList درViewBag ذخیره می کنند، سپس درون یک کادر فهرست کشویی (dropdown list box) به داده های دسته بندی دسترسی پیدا می کنند.

کد زیر نحوه ی بررسی پارامتر movieGenre را نمایش می دهد. در صورت خالی نبودن، کد مزبور query به نام movies را تا آنجایی محدود می کند که فهرست movie های انتخابی به genre تعریف شده محدود شده و فقط ژانر مورد نظر بازیابی شود.

if (!string.IsNullOrEmpty(movieGenre))

   {

      movies = movies.Where(x => x.Genre == movieGenre);

   }

همان طور که پیشتر گفته شد، query تا زمانی که لیست movies داخل حلقه نیفتاده و تکرار نشده (این امر در view و پس از اینکه متد Index بازمی گردد، رخ می دهد) بر روی پایگاه داده اجرا نمی شود.

افزودن Markup به Index View برای پشتیبانی از قابلیت جستجو بر اساس genre

یک Html.DropDownList helper  درست پیش از TextBox helper به فایل Views\Movies\Index.cshtml اضافه کنید.Markup کامل زیر نمایش داده شده است:

@model IEnumerable<MvcMovie.Models.Movie>

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>

    @Html.ActionLink("Create New", "Create")

    @using (Html.BeginForm("Index", "Movies", FormMethod.Get))

    {

    <p>

        Genre: @Html.DropDownList("movieGenre", "All")

        Title: @Html.TextBox("SearchString")

        <input type="submit" value="Filter" />

    </p>

    }

 

 

در کد زیر:

@Html.DropDownList("movieGenre""All")

پارامتر "movieGenre" با ارائه دادن کلید به  DropDownList helper به آن کمک می کند،IEnumerable<SelectListItem > را در شی ViewBag بیابد. شی ViewBag در action method پر شده (populated):

        public ActionResult Index(string movieGenre, string searchString)

{

    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies

                   orderby d.Genre

                   select d.Genre;

    GenreLst.AddRange(GenreQry.Distinct());

    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies

                 select m;

    if (!String.IsNullOrEmpty(searchString))

    {

        movies = movies.Where(s => s.Title.Contains(searchString));

    }

    if (!string.IsNullOrEmpty(movieGenre))

    {

        movies = movies.Where(x => x.Genre == movieGenre);

    }

    return View(movies);

}

  

پارامتر "All" آیتمی که باید در لیست از پیش انتخاب شود را فراهم می نماید. اگر از کد زیر استفاده می کردیم:

@Html.DropDownList("movieGenre", "Comedy")

یکی movie با ژانر "Comedy" در پایگاه داده ی خود داشته و "Comedy" در فهرست کشویی (dropdown list) از پیش انتخاب می شد. به این خاطر که ژانر "All" را نداریم، در SelectList ژانری به نام "All" وجود ندارد. بنابراین زمانی که بدون انتخاب، post back می کنیم، مقدار متغیر movieGenre query string در واقع تهی می باشد.

برنامه را اجرا کرده و به /Movies/Index پیمایش کنید. ابتدا جستجو را بر اساس genre، سپس با movie name و در آخر با هر دو معیار انجام دهید.

clip_image016[4]

در این بخش با کمک هم یک view و یک action method برای جستجو ایجاد کردیم که به کاربران اجازه می دهد بر اساس عنوان فیلم (movie title) و ژانر فیلم ها را سرچ کنند. در مبحث بعد به نحوه ی افزودن یک خاصیت به Movie و همچنین اضافه کردن یک initializer که خود به صورت پیش فرض یک پایگاه داده ی آزمایشی ایجاد می کند خواهیم پرداخت.

سه شنبه 19 آبان 1394  7:42 AM
تشکرات از این پست
itshine
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

افزودن یک فیلد جدید

افزودن یک فیلد جدید

در این بخش با بهره گیری از Entity Framework Code First Migrations، بخشی از تغییرات را به کلاس های modelانتقال داده تا تغییرات مورد نظر به کل پایگاه داده اعمال شود.

به صورت پیش فرض، هنگامی که از  EFبرای ایجاد خودکار یک پایگاه داده استفاده می کنید، همان گونه که در فصل قبلی انجام دادید، Code First با اضافه کردن یک جدول به پایگاه داده این قابلیت را فراهم می کند که بتوان بررسی و ردیابی کرد آیا schema ی پایگاه داده و کلاس های model که schema در اصل از این کلاس ها ساخته شده، با هم هماهنگ هستند یا خیر. در صورت هماهنگ نبودن این دو، EF یک پیغام خطا صادر می کند. این امر به یافتن مشکلات برنامه در زمان توسعه کمک شایانی می کند، مشکلاتی که در غیر این صورت ممکن است تنها در زمان اجرا (توسط خطاهای مبهم) از وجود آن ها آگاه شوید.

تنظیمات لازم Code First Migration برای انتقال تغییرات به کلاس های model

پنجره ی Solution Explorer را باز کنید. بر روی فایل Movies.mdf راست کلیک کرده و با انتخاب Delete، پایگاه داده ی با نام movies را حذف کنید. در صورت نیافتن فایلی به نام Movies.mdf، روی آیکون Show All Files که در کادر قرمز کوچک تصویر زیر نشان داده شده، کلیک نمایید.

image

برنامه را کامپایل (build) کرده تا از عدم وجود خطا در آن اطمینان حاصل نمایید.

از منو Tools، Library Package Manager را انتخاب نموده، سپس Package Manager Console را کلیک کنید.

image

 

 

در پنجره ی Package Manager Console و پس از اعلان خطی PM، این عبارت را وارد نمایید: Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext.

image

 

فرمان Enable-Migrations (که در تصویر زیر به نمایش گذاشته شده) یک فایل Configuration.cs در پوشه یMigrations ایجاد می کند.

 

image

 

Visual Studio فایل Configuration.cs را باز می کند. متد Seed را در فایل Configuration.cs، با کد زیر جایگزین کنید:

    protected override void Seed(MvcMovie.Models.MovieDBContext context)

{

    context.Movies.AddOrUpdate( i => i.Title,

        new Movie

        {

            Title = "When Harry Met Sally",

            ReleaseDate = DateTime.Parse("1989-1-11"),

            Genre = "Romantic Comedy",

            Price = 7.99M

        },

 

         new Movie

         {

             Title = "Ghostbusters ",

             ReleaseDate = DateTime.Parse("1984-3-13"),

             Genre = "Comedy",

             Price = 8.99M

         },

 

         new Movie

         {

             Title = "Ghostbusters 2",

             ReleaseDate = DateTime.Parse("1986-2-23"),

             Genre = "Comedy",

             Price = 9.99M

         },

 

       new Movie

       {

           Title = "Rio Bravo",

           ReleaseDate = DateTime.Parse("1959-4-15"),

           Genre = "Western",

           Price = 3.99M

       }

   );

  

}

  

روی خط های قرمز در زیر Movie راست کلیک کرده و Resolve را کلیک نمایید، سپسusing MvcMovie.Models را انتخاب کنید:

 

image

 

این کار یک دستور using به مانند زیر اضافه می کند:

using MvcMovie.Models;

Code First Migrations متد Seed را پس از هر بار انتقال (منظور فراخوانی update-database در Package Manager Console می باشد) صدا می زند، متد نام برده سطرهایی که قبلا درج شده باشند را بروز رسانی کرده و یا چنانچه این سطرها هنوز درج نشده باشند، آن ها را درج می کند.

متد AddOrUpdate در کد زیر، عملیات "upsert" بروز رسانی و درج سطر را انجام می دهد:

 

   context.Movies.AddOrUpdate(i => i.Title,

    new Movie

    {

        Title = "When Harry Met Sally",

        ReleaseDate = DateTime.Parse("1989-1-11"),

        Genre = "Romantic Comedy",

        Rating = "PG",

        Price = 7.99M

    }

از آنجایی که متد Seed با هر بار انتقال، اجرا می شود، نمی توان به راحتی اطلاعات وارد یا درج نمود، زیرا آن سطرهایی که قصد افزودن آن ها را دارید، از قبل پس از انتقال نخست که پایگاه داده طی آن ایجاد شده، درج گردیده و موجود می باشد. عملیات "upsert" از بروز خطاهایی که با سعی بر درج سطری که از قبل موجود می باشد، جلوگیری می کند ولی در این میان تغییراتی را که ممکن است حین تست برنامه به داده ها اعمال کرده باشید را بازنویسی (override) می کند. ممکن است نخواهید که این اتفاق در مورد داده های آزمایشی موجود در برخی جداول رخ دهد؛ به عبارتی دیگر مایلید داده هایی را که حین تست برنامه تغییر داده شده اند (تغییراتی که به آن ها اعمال شده اند)، آن تغییرات پس از بروز رسانی پایگاه داده نیز باقی بمانند. برای این منظور بایستی یک عملیات درج شرطی (conditional insert) پیاده کنید، به این معنی که یک سطر فقط به این شرط درج شود که از قبل وجود نداشته باشد.

اولین پارامتر ارسالی به متد AddOrUpdate، خاصیتی را که باید برای بررسی وجود یا عدم وجود سطر مورد نظر بکار رود، مشخص می کند. برای اطلاعاتی آزمایشی که ویژه ی movie فراهم می کنید، به این خاطر که هر یک از title های موجود در لیست منحصر بفرد هستند، خاصیت Titleمناسب بوده و برای نیل به این مقصود قابل استفاده می باشد:

context.Movies.AddOrUpdate(i => i.Title,

این کد فرض را بر این می گذارد که title ها منحصر بفرد هستند. اگر خودتان به صورت دستی یک title تکراری اضافه نمایید، دفعه ی بعدی که migration اجرا می کنید، خطای زیر (exception) صادر می شود:

Sequence contains more than one element

CTRL-SHIFT-B را زده تا پروژه کامپایل شود. (در صورت build نکردن پروژه در این مرحله، گام های بعدی با مشکل مواجه می شوند.)

مرحله ی بعدی ایجاد یک کلاس DbMigration برای فایل migration اولیه (initial migration) است. با این انتقال یک پایگاه داده ی جدید ایجاد می شود، به این خاطر هم است که فایل movie.mdf را در گام قبلی حذف کردید.

در پنجره ی Package Manager Console، فرمان add-migration Initial را وارد نموده تا فایل اولیه ی migration ایجاد شود. واژه ی "Initial" صرفا یک اسم برای نام گذاری فایل migration ایجاد شده است و استفاده از آن اختیاری می باشد.

image

 

Code First Migrations یک class file (به نام {DateStamp}_Initial.cs) در پوشه ی Migrations ایجاد می کند. این کلاس دربردارنده ی کدی است که schema ی پایگاه داده را ایجاد می کند. اسم فایل migration دارای یک پیشوندtimestamp است که در مرتب سازی کمک می کند. اگر فایل {DateStamp}_Initial.cs را بررسی کنید، خواهی دید که حاوی دستورهایی برای ساخت جدول Movies ویژه ی پایگاه داده ی Movie می باشد. اگر پایگاه داده را بر اساس دستورهای زیر بروز رسانی کنید، فایل {DateStamp}_Initial.cs  اجرا شده و schema ی پایگاه داده را ایجاد می کند. سپس متد Seed اجرا شده و پایگاه داده ی مربوطه را با داده های آزمایشی پر می کند.

حال به منظور ایجاد پایگاه داده و اجرای متد Seed، فرمان update-database را در Package Manager Console وارد نمایید.

image

 

اگر خطایی دریافت کردید که به حاضر (و موجود) بودن جدول مورد نظر اشاره داشت، بدانید که شما برنامه را پس از حذف پایگاه داده و پیش از اینکه دستور update-database را اجرا کنید، راه اندازی کرده اید. در صورت مواجه شدن با چنین شرایطی، بایستی فایل Movies.mdf را مجددا حذف کرده و دستور update-database را بار دیگر اجرا کنید. اگر بازهم با خطا مواجه شدید، پوشه ی migrations و تمام محتویات آن را حذف کرده و دستورات را از بالای صفحه تا پایین دنبال کنید (یعنی ابتدا فایل Movies.mdf را حذف کرده سپس به گام Enable-Migrations بپردازید).

برنامه را اجرا کرده و به آدرس  URL /Movies     بروید. داده های متد  seed  نمایش داده می شوند.

image

 

افزودن یک خاصیت به نام Rating به مدل Movie

کار خود را با افزودن یک خاصیت جدید Rating به کلاس Movie آغاز کنید. فایل Models\Movie.cs را باز کرده، سپس خاصیت Rating را مانند مثال زیر اضافه کنید:

public string Rating { get; set; }

کد کلاس کامل movie، بدین صورت خواهد بود:

    public class Movie

{

    public int ID { get; set; }

    public string Title { get; set; }

 

    [Display(Name = "Release Date")]

    [DataType(DataType.Date)]

    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

    public DateTime ReleaseDate { get; set; }

    public string Genre { get; set; }

    public decimal Price { get; set; }

    public string Rating { get; set; }

}

اکنون برنامه را کامپایل کنید (Ctrl+Shift+B).

چون که یک فیلد جدید به کلاس Movie اضافه کرده اید، لازم است white list را بروز رسانی کنید تا این خاصیت جدید نیز دربرگرفته شود. خصیصه ی bind را برای متدهای Create و Edit بروز رسانی کرده تا خاصیت Rating اضافه شود:

[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] 
 

کار دیگری که باید انجام دهید، بروز رسانی view template ها برای نمایش، ایجاد و ویرایش خاصیت Rating در browser view می باشد.

فایل \Views\Movies\Index.cshtml را باز کرده و یک عنوان ستون <th>Rating</th> درست بعد از ستون Price در سمت راست اضافه کنید. سپس یک ستون td>  <به انتهای template اضافه کرده تا مقدار @item.Rating نمایش داده شود (render). آنچه در زیر مشاهده می کنید، نسخه ی بروز رسانی شده ی Index.cshtml view template است:

@model IEnumerable<MvcMovie.Models.Movie>

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>

    @Html.ActionLink("Create New", "Create")

    @using (Html.BeginForm("Index", "Movies", FormMethod.Get))

    {

    <p>

        Genre: @Html.DropDownList("movieGenre", "All")

        Title: @Html.TextBox("SearchString")

        <input type="submit" value="Filter" />

    </p>

    }

    </p>

    <table class="table">

        <tr>

            <th>

                @Html.DisplayNameFor(model => model.Title)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.ReleaseDate)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Genre)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Price)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Rating)

            </th>

            <th></th>

        </tr>

        @foreach (var item in Model)

        {

            <tr>

                <td>

                    @Html.DisplayFor(modelItem => item.Title)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.ReleaseDate)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.Genre)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.Price)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.Rating)

                </td>

                <td>

                    @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |

                    @Html.ActionLink("Details", "Details", new { id = item.ID }) |

                    @Html.ActionLink("Delete", "Delete", new { id = item.ID })

                </td>

            </tr>

        }

 

    </table>

 

سپس فایل \Views\Movies\Create.cshtml را باز کرده و فیلد Rating را با markup رنگی شده ی زیر اضافه کنید. این کد یک text box نمایش می دهد که تا بتوان زمانی که یک movie جدید ایجاد می شود، rating آن را مشخص کرد.

<div class="form-group">

            @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })

            <div class="col-md-10">

                @Html.EditorFor(model => model.Price)

                @Html.ValidationMessageFor(model => model.Price)

            </div>

        </div>

 

        <div class="form-group">

            @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })

            <div class="col-md-10">

                @Html.EditorFor(model => model.Rating)

                @Html.ValidationMessageFor(model => model.Rating)

            </div>

        </div>

 

        <div class="form-group">

            <div class="col-md-offset-2 col-md-10">

                <input type="submit" value="Create" class="btn btn-default" />

            </div>

        </div>

    </div>

}

 

<div>

    @Html.ActionLink("Back to List", "Index")

</div>

 

@section Scripts {

    @Scripts.Render("~/bundles/jqueryval")

}

        

اکنون کد برنامه بروز رسانی شده و خاصیت Rating  به آن اضافه گردیده.

برنامه را اجرا کرده و به آدرس /Movies بروید. به هنگام انجام این کار، با یکی از خطاهای زیر مواجه می شوید:

 

image

 

Model ای که از بستر اجرا (context 'MovieDBContext' پشتیبانی می کند ، از زمانی که پایگاه داده برای اولین بار ایجاد شد،تغییر یافته.به همین دلیل توصیه میکنیم با استفاده از Code First Migration، پایگاه داده را بروز رسانی کنید(http://go.microsoft.com/fwlink/?LinkId=238269).

 

 

 

image

پیام خطای فوق به این خاطر نمایش داده شده که کلاس Movie model برنامه ی مورد نظر در حال حاضر با schema ی جدول Movie پایگاه داده ی جاری متفاوت است. (هیچ ستونی به نام  Ratingدر جدول پایگاه داده وجود ندارد.)

چندین روش برای برطرف ساختن این خطا وجود دارد:

1.     کاری کنید که EF به صورت خودکار پایگاه داده را بر اساس schema ی کلاس model جدید حذف و سپس مجددا ایجاد کند. این روش در مراحل اولیه ی چرخه ی تولید برنامه، زمانی که یک پایگاه داده ی آزمایشی را ایجاد می کنید، بسیار مفید است؛ زیرا به شما امکان می دهد model و schema ی پایگاه داده را همزمان با هم و به سرعت توسعه دهید. جنبه ی منفی آن این است که داده های موجود در پایگاه داده را از دست می دهید – از این رو تحت هیچ شرایطی نباید این روش را برای پایگاه داده ی تولیدی (production database) پیاده کنید! استفاده از یک مقداردهنده ی اولیه (initializer) برای مقداردهی (seed) خودکار یک پایگاه داده با داده های آزمایشی اغلب یک روش بسیار کارآمد برای توسعه ی برنامه محسوب می شود.

2.     Schema ی پایگاه داده ی جاری را به صورت صریح و به گونه ای اصلاح کنید که با کلاس های model منطبق باشد. از مزایای این روش این است که می توانید داده های خود را نگه دارید. می توانید این تغییر را به صورت دستی و یا با ایجاد یک change script  databaseایجاد کنید.

3.     با استفاده از Code First Migrations ،schema  ی پایگاه داده را بروز رسانی کنید.

                                                                                          در این آموزش از روش سوم بهره می گیریم.

متد Seed را بروز رسانی کرده تا مقدار ستون جدید را ارائه کند. فایل Migrations\Configuration.cs را باز کرده و یک فیلد Rating به هر شی Movie اضافه کنید.

new Movie

        {

            Title = "When Harry Met Sally",

            ReleaseDate = DateTime.Parse("1989-1-11"),

            Genre = "Romantic Comedy",

            Rating = "PG",

            Price = 7.99M

        },  

Solution مورد نظر را دوباره بسازید (build کنید)، سپس فرمان زیر را در پنجره ی Package Manager Console وارد نمایید:

add-migration Rating

فرمان add-migration به migration framework دستور می دهد که movie model جاری را با schema پایگاه داده یmovie جاری بررسی کرده و کد مورد نیاز برای انتقال (migrate) پایگاه داده به model جدید را تولید کند. واژه ی Ratingصرفا یک اسم است و برای نام گذاری فایل migration بکار می رود.

زمانی که این فرمان کاملا اجرا شده و به پایان رسید، محیط ویژوال class file ای که تعریف کننده ی کلاس مشتقDbMIgration می باشد را باز می کند. همچنین می توانید کدی که ستون جدید را ایجاد کرده در متد Up، مشاهده نمایید.

         public partial class AddRatingMig : DbMigration

{

    public override void Up()

    {

        AddColumn("dbo.Movies", "Rating", c => c.String());

    }

    public override void Down()

    {

        DropColumn("dbo.Movies", "Rating");

    }

}

Solution را مجددا ساخته (build)، سپس دستور update-database  را در پنجره ی Package Manager Console وارد نمایید.

تصویر زیر خروجی را در پنجره ی Package Manager Console به نمایش گذاشته است (date stamp ای که پیشوند واژه ی Rating می باشد، متفاوت خواهد بود).

image

 

برنامه را مجددا اجرا کرده و به آدرس /Movies بروید. اکنون می توانید فیلد Rating جدید را مشاهده کنید.

image

 

بر روی لینک Create New کلیک کرده تا یک فیلم جدید به فیلم های قبلی اضافه شود. همان طور که مشاهده می کنید، می توانید برای فیلم جدید، rating نیز ایجاد کنید.

image

 

روی دکمه ی Create کلیک کنید. فیلم جدید، به ضمیمه ی rating آن هم اکنون در فهرست فیلم ها نمایش داده می شود:

image

 

اکنون که پروژه از migrations استفاده می کند، دیگر به هنگام افزودن یک فیلد جدید یا بروز رسانی schema نیازی به حذف پایگاه داده نیست.

بایستی فیلد Rating را به view template های Edit، Details و Delete نیز اضافه کنید.

حال اگر بار دیگر فرمان  "update-database" را در پنجره ی Package Manager Console وارد کنید، هیچ کد migration ای اجرا نمی شود، زیرا که schema با model کاملا منطبق می باشد و نیازی به اجرای کد migration نیست. اما باید دقت داشته باشید که اجرای فرمان "update-database" باعث می شود متد Seed مجددا اجرا شود. اگر در این میان داده های متد Seed را تغییر دهید، تغییرات ایجاد شده از دست خواهد رفت زیرا که متد نام برده داده ها را upsert می کند.

در این مبحث با نحوه ی اصلاح اشیا model و هماهنگ نگه داشتن پایگاه داده با تغییرات آشنا شدید. همچنین چگونگی پر کردن یک پایگاه داده ی جدید با داده های نمونه برای تست را آموختید.

 

منبع : وب سایت تحلیل داده

 

سه شنبه 19 آبان 1394  7:43 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

بررسی متدهای Details و Delete

بررسی متدهای Details و Delete

در این درس، به بررسی متدهای Details و Delete که به صورت خودکار ایجاد شده اند، خواهم پرداخت.

Movie controller باز کرده و متد Details را بررسی کنید.

 

image

 

 

   public ActionResult Details(int? id)

        {

            if (id == null)

            {

                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

            }

            Movie movie = db.Movies.Find(id);

            if (movie == null)

            {

                return HttpNotFound();

            }

            return View(movie);

        }

موتور scaffolding چارچوب کاری MVC که این action method را ایجاد کرد، یک توضیح (comment) اضافه می کند که درخواست HTTP فراخواننده ی متد نام برده را مشخص می کند. در این مثال، یک درخواست GET است که دارای URL ای متشکل از سه قسمت می باشد: Movies controller، Details method و یک ID value.

Code First جستجو و یافتن داده ها را به کمک متد Find سهل می سازد. یکی از امکانات امنیتی که به صورت درون ساخته در متد وجود دارد این است که کد اطمینان حاصل کرده و بررسی می کند متد Find پیش از اینکه کد بتواند عملیاتی را بر روی آیتم (movie) انجام دهد، آیتم مورد نظر (movie) را پیدا کرده باشد.  به عنوان مثال، یک هکر می تواند با تغییر URL ای که توسط لینک ایجاد شده از آدرس http://localhost:xxxx/Movies/Details/1 به آدرسhttp://localhost:xxxx/Movies/Details/12345، error هایی را وارد سایت کند. بنابراین اگر قبلا بررسی نکرده اید که آیا فیلد null وجود دارد یا خیر، این امر ممکن است منجر به رخداد خطا در پایگاه داده شود.

متدهای Delete و DeleteConfirmed را در کد زیر بررسی کنید.

    // GET: /Movies/Delete/5

        public ActionResult Delete(int? id)

        {

            if (id == null)

            {

                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

            }

            Movie movie = db.Movies.Find(id);

            if (movie == null)

            {

                return HttpNotFound();

            }

            return View(movie);

        }

 

        // POST: /Movies/Delete/5

        [HttpPost, ActionName("Delete")]

        [ValidateAntiForgeryToken]

        public ActionResult DeleteConfirmed(int id)

        {

            Movie movie = db.Movies.Find(id);

            db.Movies.Remove(movie);

            db.SaveChanges();

            return RedirectToAction("Index");

        }

همان طور که در کد مشاهده می کنید، متد HTTP Get Delete، movie مشخص شده را حذف نمی کند، بلکه یک view ازmovie برمی گرداند که می توانید در آن deletion (HttpPost) را وارد (submit) کنید. اجرای عملیات حذف و یا هر عملیات دیگری که اطلاعات را تغییر می دهد همچون ایجاد، ویرایش و غیره .. در پاسخ به درخواست GET، باعث به وجود آمدن یک حفره ی امنیتی می شود.

متد HttpPost ای که اطلاعات را حذف می کند، DeleteConfirmed نام گذاری شده تا متد HTTP POST دارای یک ورودی (signature) یا اسم منحصر بفرد باشد. ورودی (signature) دو متد مورد نظر در زیر نمایش داده شده:

       // GET: /Movies/Delete/5

public ActionResult Delete(int? id)

 

//

// POST: /Movies/Delete/5

[HttpPost, ActionName("Delete")]

public ActionResult DeleteConfirmed(int id)

زبان مشترک زمان اجرا (CLR) ایجاب می کند که متدهای overload شده دارای یک پارامتر ورودی یا parameter signature منحصر بفرد باشند (متدی یکسان که دارای مجموعه ی متفاوتی از پارامترهاست). اما، در اینجا به دو متدDelete نیاز دارید – یکی ویژه ی GET و دیگری برای POST – که هر دو دارای پارامتر ورودی (parameter signature) یکسان باشند. (هر دو متد بایستی یک عدد صحیح را به عنوان پارامتر ورودی بپذیرد.)

برای این منظور، شما دو کار می توانید انجام دهید. اولی این است که به متدها، اسم های متفاوت تخصیص دهید. این دقیقا همان کاری است که مکانیزم scaffolding در مثال قبلی پیاده کرد. اما استفاده از این روش یک مشکل کوچک را بر سر راه شما قرار می دهد: ASP.NET بخش هایی از یک URL را بر اساس اسم به action method ها نگاشت می کند و چنانچه اسم آن متد را تغییر دهید، مسیریابی (routing) از یافتن متد مزبور ناتوان خواهد ماند. یک راه حل وجود دارد و آن در مثال زیر نمایش داده شده.

در این مثال، خصیصه ی ActionName("Delete") به متد DeleteConfirmed اضافه می شود. این کار در اصل نگاشت (mapping) را برای سیستم مسیریابی (routing system) انجام می دهد تا URL ای که (برای درخواست POST) شامل/Delete/ for می باشد، بتواند متد DeleteConfirmed را پیدا کند.

یک روش رایج دیگر برای جلوگیری از رخداد مشکل در استفاده از متدهایی که دارای اسم ها یا ورودی های (signatures) یکسان می باشند، این است که ورودی (signatures) متد POST را برای اضافه کردن پارامتر جدید (استفاده نشده) به صورت ساختگی تغییر دهید. به عنوان نمونه می توان به موردی اشاره کرد که برنامه نویس در آن یک نوع پارامتر ورودیFormCollection اضافه می کند که به متد POST ارسال می شود، ولی از آن استفاده نمی کند:

        public ActionResult Delete(FormCollection fcNotUsed, int id = 0)

        {

            Movie movie = db.Movies.Find(id);

            if (movie == null)

            {

                return HttpNotFound();

            }

            db.Movies.Remove(movie);

            db.SaveChanges();

            return RedirectToAction("Index");

        }

خلاصه

اکنون شما صاحب یک برنامه ی تحت وب ASP.NET MVC  کامل هستید که داده های خود را در یک پایگاه داده ی محلی ذخیره کرده است. می توانید در آن اطلاعات پایگاه داده را بخوانید، فیلم مورد نظر را جستجو کنید بروز رسانی و  اصلاح بر روی داده ها انجام دهید و در صورت لزوم آن ها را حذف نمایید.

 

image

 

سه شنبه 19 آبان 1394  7:43 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

آموزش ایجاد یک Data Model با استفاده از EF6 و محیط برنامه نویسی Visual 2013

در مقاله ی حاضر پروژه ی یک وب سایت ساده متعلق به دانشگاه ساختگی Contoso را مورد بررسی قرار می دهیم.

در این برنامه ی تحت وب، کاربران می توانند دانشجویان، دوره های آموزشی و اطلاعات اساتید را مشاهده و بروز رسانی کنند.

 

 

image

 

 

در نوشتن سبک رابط کاربری (UI Style) این برنامه سعی شده، آن را تا حد امکان شبیه به خروجی قالب های درون ساخته (آنچه توسط Built-in template ها ایجاد می شود) نگه داریم تا بتوان تمرکز را بیشتر بر روی نحوه ی استفاده از تکنولوژی EFگذاشت.

ساخت یک برنامه ی تحت وب MVC

Visual Studio را راه اندازی کرده و یک تحت پروژه ی وب C# به نام "ContosoUniversity" ایجاد کنید. 

 

 

image

 

 

در پنجره ی محاوره ی New ASP.NET Project، قالب MVC را انتخاب نمایید.

اگر چک باکس Host in the cloud در قسمت Microsoft Azure از قبل انتخاب شده، تیک آن را بردارید.

Change Authentication را انتخاب کنید.

 

 

image

 

 

در پنجره ی محاوره ی Change Authentication، No Authentication را انتخاب نمایید و سپس OK را کلیک کنید. برای برنامه ی که آموزش ساخت آن را در مقاله ی آموزشی حاضر می آموزیم، کاربر را ایجاب به ثبت ورود (login) نخواهیم کرد و دسترسی را بر اساس اینکه کدام کاربر وارد شده محدود نخواهیم ساخت.

 

 

image

 

 

در پنجره ی محاوره ی New ASP.NET Project، OK را کلیک کرده تا پروژه مورد نیاز ایجاد گردد.

تنظیم استایل سایت

با اعمال چندین تغییر ساده می توان منو، layout (طرح) و صفحه ی اصلی سایت را راه اندازی کرد.

فایل Views\Shared\_Layout.cshtml را باز کرده و تغییرات زیر را اعمال کنید:

1.     هر یک از نمونه های "My ASP.NET Application" و "Application name" را به "Contoso University" تغییر دهید.

2.     آیتم های لازم را برای هر یک از ورودی های Students، Courses، Instructors و Departments در منو اضافه نموده، سپس ورودی Contact را حذف نمایید.

همان طور که مشاهده می کنید، تغییرات در زیر رنگی شده اند:

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>@ViewBag.Title - Contoso University</title>

    @Styles.Render("~/Content/css")

    @Scripts.Render("~/bundles/modernizr")

</head>

<body>

    <div class="navbar navbar-inverse navbar-fixed-top">

        <div class="navbar-inner">

            <div class="container">

                <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                </button>

                @Html.ActionLink("Contoso University", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })

                <div class="nav-collapse collapse">

                    <ul class="nav">

                        <li>@Html.ActionLink("Home", "Index", "Home")</li>

                        <li>@Html.ActionLink("About", "About", "Home")</li>

                        <li>@Html.ActionLink("Students", "Index", "Student")</li>

                        <li>@Html.ActionLink("Courses", "Index", "Course")</li>

                        <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>

                        <li>@Html.ActionLink("Departments", "Index", "Department")</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

    <div class="container">

        @RenderBody()

        <hr />

        <footer>

            <p>© @DateTime.Now.Year - Contoso University</p>

        </footer>

    </div>

    @Scripts.Render("~/bundles/jquery")

    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)

</body>

</html>

 

در فایل Views\Home\Index.cshtml، محتویات صفحه را با کد زیر جایگزین کرده تا بتوان متن درباره ی ASP.NET و MVC را با متن درباره ی این برنامه جایگزین کرد:

@{

    ViewBag.Title = "Home Page";

}

<div class="jumbotron">

    <h1>Contoso University</h1>

</div>

<div class="row">

    <div class="col-md-4">

        <h2>Welcome to Contoso University</h2>

        <p>

            Contoso University is a sample application that

            demonstrates how to use Entity Framework 6 in an

            ASP.NET MVC 5 web application.

        </p>

    </div>

    <div class="col-md-4">

        <h2>Build it from scratch</h2>

        <p>You can build the application by following the steps in the tutorial series on the ASP.NET site.</p>

        <p><a class="btn btn-default" href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/">See the tutorial »</a></p>

    </div>

    <div class="col-md-4">

        <h2>Download it</h2>

        <p>You can download the completed project from the Microsoft Code Gallery.</p>

        <p><a class="btn btn-default" href="http://code.msdn.microsoft.com/ASPNET-MVC-Application-b01a9fe8">Download»</a></p>

    </div>

</div>

کلیدهای CTRL+F5 را همزمان فشار داده تا سایت اجرا شود. صفحه ی اصلی (home page) را به همراه منوی اصلی مشاهده می کنید:

 

 

image

 

 

نصب Entity Framework 6

از منو Tools، NuGet Package Manager را انتخاب کرده، سپس Package Manager Console را کلیک نمایید.

در پنجره ی Package Manager Console، دستور زیر را وارد نمایید:

Install-Package EntityFramework

 

 

image

 

 

تصویر فوق ویرایش EF 6 را در حال نصب نمایش می دهد. سرویس NuGet آخرین ویرایش EF (به استثنای نسخه نهایی) را نصب می کند که از زمان آخرین بروز رسانی این آموزش 6.1.1 می باشد.

این گام از آموزش، یکی از بخش هاست که به صورت دستی نحوه ی نصب EF را به شما آموزش می دهد. این گام توسط قابلیت scaffolding ASP.NET MVC به صورت خودکار نیز انجام می پذیرد. بخش حاضر را به این خاطر به صورت دستی انجام می دهیم تا شما بتوانید مراحل لازم برای استفاده از EF را مشاهده کرده و بیاموزید. در فصل های بعدی، controller و viewهای MVC را با استفاده از قابلیت scaffolding ایجاد خواهیم کرد.

یا به روشی دیگر می توانید به scaffolding اجازه دهید، پکیج EF NuGet را به صورت خودکار نصب، کلاس database contextرا ایجاد کرده و connection string را بسازد. در صورت تمایل به استفاده از روش دوم ، تنها کاری که باید انجام دهید این است که تمامی مراحل لازم برای نصب دستی را نادیده گرفته و بلافاصله کلاس های entity خود را ایجاد کنید.

ایجاد Data Model

حال به ایجاد کلاس های entity برای برنامه ی Contoso University خواهیم پرداخت. کار خود را با سه ورودی زیر آغاز می کنیم:

 

 

 

image

 

 

بین entity های (موجودیت) Student و Enrollment  و همچنین بین Course و Enrollment یک رابطه ی یک به چند وجود دارد. به عبارتی دیگر، یک دانشجو (student) می تواند در چند دوره ی آموزشی (course) ثبت نام کند و نیز یک دوره ی آموزشی می تواند تعدادی دانشجو داشته باشد که در آن ثبت کرده اند.

در بخش های زیر به ازای هر یک از entity ها یک کلاس ایجاد می کنیم.

توجه: چنانچه پیش از اینکه تمامی کلاس های entity را ایجاد کرده باشید، اقدام به کامپایل پروژه بکنید، با خطاهایی مربوط به compiler مواجه می شوید.

 

 

image

 

 

در پوشه ی Models، یک class file به نام Student.cs ایجاد کرده و کد template را با کد زیر جایگزین نمایید:

       using System;

using System.Collections.Generic;

 

namespace ContosoUniversity.Models

{

    public class Student

    {

        public int ID { get; set; }

        public string LastName { get; set; }

        public string FirstMidName { get; set; }

        public DateTime EnrollmentDate { get; set; }

       

        public virtual ICollection<Enrollment> Enrollments { get; set; }

    }

}

خاصیت ID ستون کلید اصلی (primary key column) جدول پایگاه داده خواهد بود که با این کلاس متناظر می باشد. به صورت پیش فرض، EF خاصیتی (propery) که ID یا classnameID نام گذاری شده را به عنوان کلید اصلی شناخته و تفسیر می کند.

خاصیت Enrollments، درواقع یک navigation property است. navigation property ها موجودیت های دیگر را نگه می دارند که به این entity مربوط می باشند. در این نمونه، خاصیت Enrollments موجودیت Student ، تمامی موجودیت هایEnrollments که مربوط به Student هستند را نگه می دارد. به عبارتی دیگر، اگر یک سطر به خصوص از  موجودیت Student در پایگاه داده ی مورد نظر دارای دو سطر مربوطه ی Enrollments باشد (سطرهایی که دربردارنده ی مقدار کلید اصلی (primary key valuestudent در ستون کلید خارجی StudentID (foreign key column) هستند)، Enrollments navigation propertyموجودیت آن Student، دربردارنده ی آن دو موجودیت Enrollment خواهد بود.

Navigation property ها معمولا با کلیدواژه ی virtual تعریف می شوند، تا بدین وسیله بتوانند از برخی از قابلیت های EFهمچون lazy loading (بارگذاری با تاخیر) بهره بگیرند.

اگر یک navigation property بتواند به طور همزمان چندین entity را نگه دارد (مانند آنچه در رابطه ی چند به چند یا یک به چند اتفاق می افتد)، در آن صورت، navigation property بایستی از نوع لیست باشد تا بتوان ورودی هایی را به آن اضافه، بروز رسانی کرد یا در صورت لزوم حذف نمود مانند ICollection

 

 

image

 

 

در پوشه ی Models، فایل Enrollment.cs را ایجاد کرده و کد موجود را با کد زیر جایگزین نمایید:

 

namespace ContosoUniversity.Models

{

    public enum Grade

    {

        A, B, C, D, F

    }

    public class Enrollment

    {

        public int EnrollmentID { get; set; }

        public int CourseID { get; set; }

        public int StudentID { get; set; }

        public Grade? Grade { get; set; }

       

        public virtual Course Course { get; set; }

        public virtual Student Student { get; set; }

    }

}

خاصیت EnrollmentID کلید اصلی (primary key) خواهد بود؛ این entity بجای ID به تنهایی، از الگوی classnameIDاستفاده می کند، همان طور که در موجودیت Student مشاهده گر آن بودید. به طور معمول یک الگو را انتخاب می کنیم و آن را در کل data model خود بکار می بریم. در اینجا، تغییر کوچکی که مشاهده کردید، نشانگر این است که می توان از هر دو الگو استفاده کرد.

خاصیت Grade ورودی از نوع شمارشی (enum) می پذیرد. علامت سوال پس از تعریف نوع Grade، بر این قضیه اشاره دارد که خاصیت Grade، nullable می باشد. لازم به ذکر است یک نمره (grade) که null یا تهی می باشد، از نمره ی صفر کاملا متفاوت است – null بیانگر این است که آن grade تعریف نشده یا هنوز مقداری به آن تخصیص نیافته است.

خاصیت StudentID یک کلید خارجی است و navigation property متناظر با آن Student می باشد. یک entity یا موجودیتEnrollment به یک Student مربوط می باشد، بنابراین خاصیت مورد نظر تنها می تواند یک موجودیت Student را نگه دارد (بر خلاف Student.Enrollments navigation property که کمی پیشتر مشاهده کردید که قادر است چندین موجودیتEnrollment نگه دارد.)

خاصیت CourseID یک کلید خارجی است و navigation property مربوط با آن نیز Course می باشد. یک موجودیتEnrollment تنها به یک موجودیت Course مربوط یا متصل می باشد.

EF، در صورتی که خاصیتی <navigation property name><primary key property name> نام گذاری شده باشد، آن خاصیت را به عنوان یک خاصیت کلید خارجی (foreign key property) تفسیر می کند (به عنوان مثال، StudentID برایStudent navigation property زیرا که کلید اصلی موجودیت Student، ID می باشد). همین کار را می توان برای خاصیت های کلید خارجی (Foreign key properties) نیز انجام داد، <primary key property name> (به عنوان مثال، CourseID زیرا که کلید اصلی موجودیتCourse ، CourseIDمی باشد ).

 

 

image

 

 

در پوشه ی Models، Course.cs را ایجاد کرده و کد template را با کد زیر جایگزین کنید:

using System.Collections.Generic;

using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models

{

    public class Course

    {

        [DatabaseGenerated(DatabaseGeneratedOption.None)]

        public int CourseID { get; set; }

        public string Title { get; set; }

        public int Credits { get; set; }

        public virtual ICollection<Enrollment> Enrollments { get; set; }

    }

}

خاصیت Enrollments یک navigation property می باشد. یک موجودیت Course ممکن است به چندین موجودیتEnrollment مربوط باشد.

بعده ها درباره ی خصیصه ی DatabaseGenerated بیشتر بحث خواهیم کرد. خصیصه ی نام برده اساسا به شما اجازه می دهد بجای اینکه کاری کنید پایگاه داده کلید اصلی را خود بسازد آن را برای course مورد نظر وارد نمایید.

ایجاد Database Context

کلاس اصلی که قابلیت EF را برای یک data model معین هماهنگ سازی می کند، کلاس database context است. کلاس ذکر شده را با ارث بری از کلاس System.Data.Entity.DbContext ایجاد می کنیم. در کد خود مشخص می کنیم کدام entity ها درdata model گنجانده شوند، حتی می توانید برخی از رفتارهای EF را سفارشی تنظیم کنید. در این پروژه اسم کلاس راSchoolContext انتخاب می کنیم.

به منظور ایجاد یک پوشه در پروژه ی ContosoUniversity، بر روی پروژه در پنجره ی Solution Explorer راست کلیک کرده وAdd را کلیک کنید. سپس بر روی New Folder کلیک نمایید. پوشه ی جدید را DAL (Data Access Layer) نام گذاری کنید. در آن پوشه یک فایل کلاس جدید به نام SchoolContext.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید:

    using ContosoUniversity.Models;

    using System.Data.Entity;

    using System.Data.Entity.ModelConfiguration.Conventions;

 

    namespace ContosoUniversity.DAL

    {

        public class SchoolContext : DbContext

        {

            public SchoolContext()

                : base("SchoolContext")

            {

            }

            public DbSet<Student> Students { get; set; }

            public DbSet<Enrollment> Enrollments { get; set; }

            public DbSet<Course> Courses { get; set; }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)

            {

                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            }

        }

    }

تعریف entity set ها (مجموعه ای از جداول)

این کد یک خاصیت DbSet ویژه ی هر entity set ایجاد می کند. در EF منظور از entity set همان جدول در پایگاه داده و entityنیز یک سطر یا ردیف از جدول است.

اگر دستورهای DbSet < Enrollment>و DbSet<Course> را هم حذف کنید باز در روند اجرا هیچ تغییر اتفاق نمی افتاد. EF آن ها را به صورت ضمنی مورد ارجاع قرار می داد (اضافه می کرد)، به این ترتیب که موجودیت Student به موجودیتEnrollment اشاره می کند و موجودیت Enrollment نیز به موجودیت Course اشاره می کند.

تعریف connection string

اسم connection string (که بعدا آن را به فایل Web.config اضافه خواهیم کرد) به constructor ارسال می شود.

    public SchoolContext() : base("SchoolContext")

{

}

همچنین می توانستید بجای اسم connection string که در فایل Web.config ذخیره می شود، خود connection string را بهconstructor ارسال نمایید.

اگر یک connection string معین یا اسم connection string را به صورت صریح تعریف نکنید، EF فرض می گیرد که اسمconnection string با اسم کلاس یکی است. اسم پیش فرض connection string در این مثال، SchoolContext خواهد بود، یکسان با آنچه به صورت صریح تعریف می کنید. 

تعریف اسامی جدول به صورت فردی و جمعی

دستور modelBuilder.Conventions.Remove در متد OnModelCreating مانع از این می شود که اسامی جدول به صورت جمعی تعریف شوند. اگر این کار نمی کردیم، جداول ایجاد شده به ترتیب Students، Courses و Enrollments نام گذاری می شدند. با استفاده از این دستور، اسامی جداول Student، Course و Enrollment به صورت فردی و بدون s جمع نام گذاری شده اند. برنامه نویسان در رابطه با اینکه آیا اسم جداول به صورت جمعی تعریف شوند یا فردی، اختلاف نظر دارند. در مقاله ی حاضر از اسم فردی برای جداول بهره گرفته شده، اما شما می توانید مطابق میل خود با اضافه یا حذف کردن این خط کد، اسم جدول را فرد یا جمع تعریف کنید.

   تنظیمEF  جهت مقداردهی اولیه پایگاه داده با داده های آزمایش

EF قادر است هنگامی که برنامه اجرا می شود به صورت خودکار یک پایگاه داده را ایجاد (یا حذف و مجدد ایجاد) کند. این امکان برای شما وجود دارد که مشخص کنید آیا هر بار که برنامه اجرا می شود، پایگاه داده خودکار ایجاد گردد یا فقط زمانی کهmodel با پایگاه داده ی موجود همگام نیست، این اتفاق رخ دهد. همچنین می توانید یک متد Seed بنویسید که EF خودکار پس از ایجاد کردن پایگاه داده صدا می زند و به وسیله آن پایگاه داده ی مورد نظر را با داده های آزمایشی پر می کند.

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

در پوشه ی DAL، یک فایل کلاس جدید به نام SchoolInitializer.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید. این کار باعث می شود پایگاه داده در صورت نیاز ایجاد شده و داده های آزمایشی در پایگاه داده ی جدید بارگذاری شوند.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Data.Entity;

using ContosoUniversity.Models;

namespace ContosoUniversity.DAL

{

    public class SchoolInitializer : System.Data.Entity. DropCreateDatabaseIfModelChanges<SchoolContext>

    {

        protected override void Seed(SchoolContext context)

        {

            var students = new List<Student>

            {

            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-0901")},

            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},

            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},

            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},

            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}

            };

            students.ForEach(s => context.Students.Add(s));

            context.SaveChanges();

            var courses = new List<Course>

            {

            new Course{CourseID=1050,Title="Chemistry",Credits=3,},

            new Course{CourseID=4022,Title="Microeconomics",Credits=3,},

            new Course{CourseID=4041,Title="Macroeconomics",Credits=3,},

            new Course{CourseID=1045,Title="Calculus",Credits=4,},

            new Course{CourseID=3141,Title="Trigonometry",Credits=4,},

            new Course{CourseID=2021,Title="Composition",Credits=3,},

            new Course{CourseID=2042,Title="Literature",Credits=4,}

            };

            courses.ForEach(s => context.Courses.Add(s));

            context.SaveChanges();

            var enrollments = new List<Enrollment>

            {

            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},

            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},

            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},

            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},

            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},

            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},

            new Enrollment{StudentID=3,CourseID=1050},

            new Enrollment{StudentID=4,CourseID=1050,},

            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},

            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},

            new Enrollment{StudentID=6,CourseID=1045},

            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},

            };

            enrollments.ForEach(s => context.Enrollments.Add(s));

            context.SaveChanges();

        }

    }

}

متد Seed، شی database context را به عنوان پارامتر ورودی می پذیرد، کد داخل متد به وسیله ی آن شی entity های جدید را به پایگاه داده اضافه می کند. به ازای هر entity type، کد یک مجموعه ی جدید از entity ها را ایجاد کرده و آن ها را به خاصیت DbSet مربوطه اضافه می کند، سپس تغییرات ایجاد شده را در پایگاه داده ذخیره می کند. ضرورتی ندارد متدSaveChanges را بعد از هر مجموعه entity (همان گونه که در این آموزش صورت گرفته) فراخوانی کرد. با این حال، انجام آن به شما کمک می کند در صورت رخداد خطا زمانی که کد در حال نوشته شدن در پایگاه داده هست، منشا یک مشکل را شناسایی کنید.

برای اینکه به EF دستور دهید از initializer class شما استفاده کند، یک المان را به عنصر entityFramework در فایلWeb.config (موجود در root folder پروژه) اضافه نمایید:

  <entityFramework>

  <contexts>

    <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">

      <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />

    </context>

  </contexts>

  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">

    <parameters>

      <parameter value="v11.0" />

    </parameters>

  </defaultConnectionFactory>

  <providers>

    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />

  </providers>

</entityFramework>

context type اسم کلاس context که به صورت کامل تعریف شده را به همراه assembly ای که در آن جای گرفته مشخص می کند. databaseinitializer type اسم کلاس initializer که به طور کامل تعریف شده را به همراه assembly ای که در آن قرار گرفته، مشخص می کند. (اگر نمی خواهید که EF از initializer استفاده کند، می توانید خصیصه ی disableDatabaseInitialization="true"را بر روی المان context تعریف کنید)

یک روش جایگزین برای تنظیم initializer در فایل Web.config، تنظیم آن در کد با اضافه کردن یک دستورDatabase.SetInitializer به متد Application_Start در فایل Global.asax.cs است.

اکنون برنامه به گونه ای تنظیم شده، که هنگامی که شما برای بار نخست در یکبار اجرای برنامه به پایگاه داده دسترسی پیدا می کنید، EF پایگاه داده را با model (SchoolContext و کلاس های entity) مقایسه می کند و در صورت برخورد با هر گونه تفاوت بین این دو، پایگاه داده را حذف کرده و آن را مجدد ایجاد می کند.

توجه: هنگامی که شما برنامه را روی web server تولیدی خود مستقر می کنید، بایستی کدی را که پایگاه داده را حذف و بازسازی می کند، غیر فعال نمایید.

تنظیم EF برای استفاده از یک نسخه ی LocalDB پایگاه داده ی SQL Server Express

LocalDB یک نسخه ی کم حجم از موتور پایگاه داده ی SQL Server Express است. نصب و پیکربندی آن بسیار ساده می باشد، به مجرد تقاضا و بنا به درخواست آغاز شده و در حالت user mode اجرا می شود. LocalDB در یک حالت اجرایی ویژه ازSQL Server Express اجرا می شود که به شما این امکان را می دهد، با پایگاه های داده مانند فایل های .mdf برخورد کنید.

اگر می خواهید پایگاه داده را همراه با پروژه کپی کنید، می توانید فایل های پایگاه داده ی LocalDB را در پوشه ی App_Data یک پروژه ی وب جای گذاری نمایید. امکان user instance در SQL Server Express نیر به شما اجازه می دهد با فایل های.mdf کار کنید، اما استفاده از این امکان توصیه نمی شود، بنابراین تنها LocalDB مناسب کار با فایل های .mdf می باشد. در ویرایش 2012 و جدیدتر Visual Studio، LocalDB به صورت پیش فرض توسط خود محیط نصب می شود.

به طور معمول SQL Server Express، به خصوص نسخه ی LocalDB آن برای برنامه های تولیدی تحت وب (production web applications) مورد استفاده قرار نمی گیرد (و برای کار با برنامه های تحت وب مناسب نمی باشد)، زیرا که نسخه ی ذکر شده اساسا برای کار با IIS طراحی نشده.

در این آموزش با LocalDB کار خواهیم کرد. فایل برنامه ی Web.config را باز کرده و یک المان connectionStrings پیش از المان appSettings اضافه نمایید. (فایل Web.config را حتما در root folder پروژه بروز رسانی کنید. البته یک فایلWeb.config دیگر در زیرپوشه ی Views وجود دارد که نیاز به بروز رسانی آن نیست.)

در صورت استفاده از Visual Studio 2015، لازم است به این خاطر که اسم پیش فرض نمونه ی SQL Server تغییر یافته، "v11.0" را داخل connection string با "MSSQLLocalDB" جایگزین کنید.

<connectionStrings>

  <add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity1;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>

</connectionStrings>

<appSettings>

  <add key="webpages:Version" value="3.0.0.0" />

  <add key="webpages:Enabled" value="false" />

  <add key="ClientValidationEnabled" value="true" />

  <add key="UnobtrusiveJavaScriptEnabled" value="true" />

</appSettings>

 

Connection string ای که اضافه کردید، تعریف می کند که EF از یک پایگاه داده ی LocalDB به نامContosoUniversity1.mdf استفاده کند.(پایگاه داده ای هنوز ایجاد نشده؛ ولی EF آن را ایجاد می کند.) اگر می خواستید پایگاه داده در پوشه ی App_Data ایجاد شود، در آن صورت می بایستAttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf را به connection string اضافه می کردید. 

لزومی ندارد در فایل Web.config، یک connection string ایجاد کنید. در صورت فراهم نکردن connection string، EF بر اساس کلاس context شما، از یک connection string پیش فرض استفاده می کند.

ایجاد یک controller و views به نام Student

اکنون یک صفحه ی وب خواهیم ساخت که داده های ما را نمایش می دهد، فرایند درخواست داده به صورت خودکار پروسه ی ساخت پایگاه داده را فعال می کند. کار خود را با ایجاد یک controller آغاز خواهیم کرد. اما پیش از آن باید پروژه را کامپایل کرده (build) تا کلاس های model و context در اختیار MVC controller scaffolding قرار گیرد.

1.     بر روی پوشه ی Controllers در Solution Explorer راست کلیک کرده، Add را انتخاب کنید، سپس New Scaffolded Item را کلیک نمایید.

2.     در پنجره ی محاوره ی Add Scaffold، MVC 5 Controller with views, using Entity Framework را انتخاب نمایید.

 

 

image

 

 

3.     در پنجره ی محاوره ی Add Controller، به ترتیب زیر اقدام کنید:

Model class: Student (ContosoUniversity.Models )

Data context class: SchoolContext (ContosoUniversity.DAL )

Controller name: StudentController

مقادیر فیلدهای دیگر را تغییر ندهید.

 

 

 

 

image

 

 

هنگامی که بر روی Add کلیک می کنید، scaffolder یک فایل StudentController.cs و مجموعه ای از view ها (فایل های.cshtml) را ایجاد می کند که با controller کار می کنند. در پروژه هایی که در آینده ایجاد می کنید و در آن ها از EF استفاده می کنید، می توانید از تعدادی قابلیت اضافی scaffolder بهره بگیرید: کافی است اولین کلاس model خود را ایجاد کرده، سپس در کادر Add Controller، یک کلاس context جدید تعریف کنید(در این مرحله از تعریف connection string خودداری نمایید).Scaffolder خود کلاس DbContext و connection string را به ضمیمه ی controller و view ها ایجاد می کند. 

4.     Visual Studio، فایل Controllers\StudentController.cs را باز می کند. خواهید دید که یک class variable اضافه شده که database context object را مقداردهی اولیه می کند:

private SchoolContext db = new SchoolContext();

متد اکشن Index یک لیست از دانشجویان را از entity set به نام Students بازیابی می کند. این کار با خواندن خاصیتStudents از نمونه ی database context صورت می گیرد:

         public ViewResult Index()

{

    return View(db.Students.ToList());

}

Student\Index.cshtml view ، این لیست را در یک جدول نمایش می دهد:

<table>

    <tr>

        <th>

            @Html.DisplayNameFor(model => model.LastName)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.FirstMidName)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.EnrollmentDate)

        </th>

        <th></th>

    </tr>

 

    @foreach (var item in Model)

    {

        <tr>

            <td>

                @Html.DisplayFor(modelItem => item.LastName)

            </td>

            <td>

                @Html.DisplayFor(modelItem => item.FirstMidName)

            </td>

            <td>

                @Html.DisplayFor(modelItem => item.EnrollmentDate)

            </td>

            <td>

                @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |

                @Html.ActionLink("Details", "Details", new { id = item.ID }) |

                @Html.ActionLink("Delete", "Delete", new { id = item.ID })

            </td>

        </tr>

    }

</table>

       

2.     CTRL+F5 را زده تا پروژه اجرا شود. (در صورت برخورد با خطای "Cannot create Shadow Copy"، مرورگر را بسته و مجددا امتحان کنید.)

روی تب Students کلیک کرده تا داده هایی که توسط متد Seed درج گردیده را مشاهده نمایید. اگر پنجره ی مرورگر باریک بود، باید بر گوشه ی بالا، سمت راست کلیک کنید و یا در صورت بزرگ بودن پنجره، می توانید لینک تب Students را در نوار آدرس بالای پنجره ببینید و انتخاب کنید.

 

 

image

 

 

 

image

 

مشاهده ی پایگاه داده

هنگامی که صفحه ی Students را اجرا کردید و برنامه سعی کرد به پایگاه داده دسترسی پیدا کند، EF متوجه می شود که پایگاه داده ای ایجاد نشده، بنابراین خود یک پایگاه داده ایجاد کرده، سپس با اجرا کردن متد seed پایگاه داده را با داده های آزمایشی پر می کند.

برای مشاهده ی پایگاه داده در محیط Visual Studio، می توان از Server Explorer یا SQL Server Object Explorer استفاده کرد. در این آموزش از Server Explorer استفاده خواهیم کرد (در نسخه های پیش از 2013، Server Explorer، Database Explorer خوانده می شود.)

1.     مرورگر را ببندید.

2.     در پنجره ی Server Explorer، Data Connections => School Context (ContosoUniversity) و سپس Tables را باز کرده تا جداول را در پایگاه داده ی جدید خود مشاهده کنید:

 

 

image

 

 

3.     روی جدول Student راست کلیک کرده و بر روی Show Table Data کلیک کنید تا ستون هایی که ایجاد شده و سطرهایی که در جدول درج گردیده را مشاهده کنید.

 

image

 

 

4.     اتصال Server Explorer را قطع کنید.

فایل های ContosoUniversity1.mdf و .ldf در پوشه ی C:\Users\yourusername>> قرار دارند.

به این خاطر که شما از DropCreateDatabaseIfModelChanges initializer استفاده می کنید، می توانید تغییراتی را به کلاسStudent اعمال نمایید، حال برنامه را مجدد اجاره کنید، خواهید دید که پایگاه داده به صورت خودکار مجدد ایجاد شده و خود را با تغییراتی که شما اعمال کرده اید، مطابق می کند. به عنوان مثال، اگر خاصیت EmailAddress را به کلاس Student اضافه کنید و صفحه ی students را مجدد اجرا کنید، سپس به جدول مورد نظر مراجعه کنید، خواهید دید که یک ستون جدید به نامEmailAddress اضافه شده است.

مقدار کدی که بایستی می نوشتید تا EF بتواند یک پایگاه داده ی کامل را ایجاد کند، به دلیل وجود قرارداد ها (conventionها) بسیار کم بود. متوجه برخی از آن ها شدید و برخی هم گونه ای بودند که از وجود و اجرای آن ها آگاه نبودید:

1.     صورت جمع اسم های کلاس entity که به عنوان اسم جداول مورد استفاده واقع شدند.

2.     اسم های property های entity که برای اسم ستون بکار برده شدند.

3.     خاصیت های entity که ID یا classnameID نام گذاری شدند و به عنوان خاصیت های primary key شناخته می شوند.

4.     یک خاصیت زمانی به عنوان foreign key در نظرگرفته می شوند که بدین صورت نام گذاری شده باشد <navigation property name><primary key property name> (به عنوان مثال، می توان به StudentID برای Student navigation property اشاره کرد، زیرا که کلید اصلی موجودیت Student، ID می باشد). خواص foreign key را نیز می توان به همان شیوه نام گذاری کرد <primary key property name>. (به عنوان مثال، EnrollmentID زیرا که کلید اصلی موجودیت Enrollment،  EnrollmentIDمی باشد).

همچنین مشاهده کردید که قرار دادها را می توان باطل کرده و بازنویسی کرد. برای مثال، تعیین کردید که اسم جداول به صورت جمع تعریف نشوند.

چکیده

در این درس یک برنامه ی ساده ایجاد کردید با بهره گیری از تکنولوژی EF و نسخه ی LocalDB اس کیو ال سرور اکسپرس داده ها را ذخیره کرده و به نمایش گذاشت. در مبحث بعدی با نحوه ی انجام عملیات ساده CRUD آشنا خواهید شد.

سه شنبه 19 آبان 1394  7:44 AM
تشکرات از این پست
mtk_designer
mtk_designer
کاربر برنزی
تاریخ عضویت : آذر 1390 
تعداد پست ها : 157

ایجاد یک Data Model با استفاده از EF6

آموزش ایجاد یک Data Model با استفاده از EF6 و محیط برنامه نویسی Visual 2013

 

در مقاله ی حاضر پروژه ی یک وب سایت ساده متعلق به دانشگاه ساختگی Contoso را مورد بررسی قرار می دهیم.

در این برنامه ی تحت وب، کاربران می توانند دانشجویان، دوره های آموزشی و اطلاعات اساتید را مشاهده و بروز رسانی کنند.

 

 

image

 

 

در نوشتن سبک رابط کاربری (UI Style) این برنامه سعی شده، آن را تا حد امکان شبیه به خروجی قالب های درون ساخته (آنچه توسط Built-in template ها ایجاد می شود) نگه داریم تا بتوان تمرکز را بیشتر بر روی نحوه ی استفاده از تکنولوژیEF گذاشت.

ساخت یک برنامه ی تحت وب MVC

Visual Studio را راه اندازی کرده و یک تحت پروژه ی وب C# به نام "ContosoUniversity" ایجاد کنید. 

 

 

image

 

 

در پنجره ی محاوره ی New ASP.NET Project، قالب MVC را انتخاب نمایید.

اگر چک باکس Host in the cloud در قسمت Microsoft Azure از قبل انتخاب شده، تیک آن را بردارید.

Change Authentication را انتخاب کنید.

 

 

image

 

 

در پنجره ی محاوره ی Change Authentication، No Authentication را انتخاب نمایید و سپس OK را کلیک کنید. برای برنامه ی که آموزش ساخت آن را در مقاله ی آموزشی حاضر می آموزیم، کاربر را ایجاب به ثبت ورود (login) نخواهیم کرد و دسترسی را بر اساس اینکه کدام کاربر وارد شده محدود نخواهیم ساخت.

 

 

image

 

 

در پنجره ی محاوره ی New ASP.NET Project، OK را کلیک کرده تا پروژه مورد نیاز ایجاد گردد.

تنظیم استایل سایت

با اعمال چندین تغییر ساده می توان منو، layout (طرح) و صفحه ی اصلی سایت را راه اندازی کرد.

فایل Views\Shared\_Layout.cshtml را باز کرده و تغییرات زیر را اعمال کنید:

1.     هر یک از نمونه های "My ASP.NET Application" و "Application name" را به "Contoso University" تغییر دهید.

2.     آیتم های لازم را برای هر یک از ورودی های Students، Courses، Instructors و Departments در منو اضافه نموده، سپس ورودی Contact را حذف نمایید.

همان طور که مشاهده می کنید، تغییرات در زیر رنگی شده اند:

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>@ViewBag.Title - Contoso University</title>

    @Styles.Render("~/Content/css")

    @Scripts.Render("~/bundles/modernizr")

</head>

<body>

    <div class="navbar navbar-inverse navbar-fixed-top">

        <div class="navbar-inner">

            <div class="container">

                <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                    <span class="icon-bar"></span>

                </button>

                @Html.ActionLink("Contoso University", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })

                <div class="nav-collapse collapse">

                    <ul class="nav">

                        <li>@Html.ActionLink("Home", "Index", "Home")</li>

                        <li>@Html.ActionLink("About", "About", "Home")</li>

                        <li>@Html.ActionLink("Students", "Index", "Student")</li>

                        <li>@Html.ActionLink("Courses", "Index", "Course")</li>

                        <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>

                        <li>@Html.ActionLink("Departments", "Index", "Department")</li>

                    </ul>

                </div>

            </div>

        </div>

    </div>

    <div class="container">

        @RenderBody()

        <hr />

        <footer>

            <p>© @DateTime.Now.Year - Contoso University</p>

        </footer>

    </div>

    @Scripts.Render("~/bundles/jquery")

    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)

</body>

</html>

 

در فایل Views\Home\Index.cshtml، محتویات صفحه را با کد زیر جایگزین کرده تا بتوان متن درباره ی ASP.NET وMVC را با متن درباره ی این برنامه جایگزین کرد:

@{

    ViewBag.Title = "Home Page";

}

<div class="jumbotron">

    <h1>Contoso University</h1>

</div>

<div class="row">

    <div class="col-md-4">

        <h2>Welcome to Contoso University</h2>

        <p>

            Contoso University is a sample application that

            demonstrates how to use Entity Framework 6 in an

            ASP.NET MVC 5 web application.

        </p>

    </div>

    <div class="col-md-4">

        <h2>Build it from scratch</h2>

        <p>You can build the application by following the steps in the tutorial series on the ASP.NET site.</p>

        <p><a class="btn btn-default" href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/">See the tutorial »</a></p>

    </div>

    <div class="col-md-4">

        <h2>Download it</h2>

        <p>You can download the completed project from the Microsoft Code Gallery.</p>

        <p><a class="btn btn-default" href="http://code.msdn.microsoft.com/ASPNET-MVC-Application-b01a9fe8">Download »</a></p>

    </div>

</div>

کلیدهای CTRL+F5 را همزمان فشار داده تا سایت اجرا شود. صفحه ی اصلی (home page) را به همراه منوی اصلی مشاهده می کنید:

 

 

image

 

 

نصب Entity Framework 6

از منو Tools، NuGet Package Manager را انتخاب کرده، سپس Package Manager Console را کلیک نمایید.

در پنجره ی Package Manager Console، دستور زیر را وارد نمایید:

Install-Package EntityFramework

 

 

image

 

 

تصویر فوق ویرایش EF 6 را در حال نصب نمایش می دهد. سرویس NuGet آخرین ویرایش EF (به استثنای نسخه نهایی) را نصب می کند که از زمان آخرین بروز رسانی این آموزش 6.1.1 می باشد.

این گام از آموزش، یکی از بخش هاست که به صورت دستی نحوه ی نصب EF را به شما آموزش می دهد. این گام توسط قابلیت scaffolding ASP.NET MVC به صورت خودکار نیز انجام می پذیرد. بخش حاضر را به این خاطر به صورت دستی انجام می دهیم تا شما بتوانید مراحل لازم برای استفاده از EF را مشاهده کرده و بیاموزید. در فصل های بعدی،controller و view های MVC را با استفاده از قابلیت scaffolding ایجاد خواهیم کرد.

یا به روشی دیگر می توانید به scaffolding اجازه دهید، پکیج EF NuGet را به صورت خودکار نصب، کلاس database context را ایجاد کرده و connection string را بسازد. در صورت تمایل به استفاده از روش دوم ، تنها کاری که باید انجام دهید این است که تمامی مراحل لازم برای نصب دستی را نادیده گرفته و بلافاصله کلاس های entity خود را ایجاد کنید.

ایجاد Data Model

حال به ایجاد کلاس های entity برای برنامه ی Contoso University خواهیم پرداخت. کار خود را با سه ورودی زیر آغاز می کنیم:

 

 

 

image

 

 

بین entity های (موجودیت) Student و Enrollment  و همچنین بین Course و Enrollment یک رابطه ی یک به چند وجود دارد. به عبارتی دیگر، یک دانشجو (student) می تواند در چند دوره ی آموزشی (course) ثبت نام کند و نیز یک دوره ی آموزشی می تواند تعدادی دانشجو داشته باشد که در آن ثبت کرده اند.

در بخش های زیر به ازای هر یک از entity ها یک کلاس ایجاد می کنیم.

توجه: چنانچه پیش از اینکه تمامی کلاس های entity را ایجاد کرده باشید، اقدام به کامپایل پروژه بکنید، با خطاهایی مربوط به compiler مواجه می شوید.

 

 

image

 

 

در پوشه ی Models، یک class file به نام Student.cs ایجاد کرده و کد template را با کد زیر جایگزین نمایید:

       using System;

using System.Collections.Generic;

 

namespace ContosoUniversity.Models

{

    public class Student

    {

        public int ID { get; set; }

        public string LastName { get; set; }

        public string FirstMidName { get; set; }

        public DateTime EnrollmentDate { get; set; }

       

        public virtual ICollection<Enrollment> Enrollments { get; set; }

    }

}

خاصیت ID ستون کلید اصلی (primary key column) جدول پایگاه داده خواهد بود که با این کلاس متناظر می باشد. به صورت پیش فرض، EF خاصیتی (propery) که ID یا classnameID نام گذاری شده را به عنوان کلید اصلی شناخته و تفسیر می کند.

خاصیت Enrollments، درواقع یک navigation property است. navigation property ها موجودیت های دیگر را نگه می دارند که به این entity مربوط می باشند. در این نمونه، خاصیت Enrollments موجودیت Student ، تمامی موجودیت های Enrollments که مربوط به Student هستند را نگه می دارد. به عبارتی دیگر، اگر یک سطر به خصوص از  موجودیتStudent در پایگاه داده ی مورد نظر دارای دو سطر مربوطه ی Enrollments باشد (سطرهایی که دربردارنده ی مقدار کلید اصلی (primary key valuestudent در ستون کلید خارجی StudentID (foreign key column) هستند)، Enrollments navigation property موجودیت آن Student، دربردارنده ی آن دو موجودیت Enrollment خواهد بود.

Navigation property ها معمولا با کلیدواژه ی virtual تعریف می شوند، تا بدین وسیله بتوانند از برخی از قابلیت هایEF همچون lazy loading (بارگذاری با تاخیر) بهره بگیرند.

اگر یک navigation property بتواند به طور همزمان چندین entity را نگه دارد (مانند آنچه در رابطه ی چند به چند یا یک به چند اتفاق می افتد)، در آن صورت، navigation property بایستی از نوع لیست باشد تا بتوان ورودی هایی را به آن اضافه، بروز رسانی کرد یا در صورت لزوم حذف نمود مانند ICollection

 

 

image

 

 

در پوشه ی Models، فایل Enrollment.cs را ایجاد کرده و کد موجود را با کد زیر جایگزین نمایید:

 

namespace ContosoUniversity.Models

{

    public enum Grade

    {

        A, B, C, D, F

    }

    public class Enrollment

    {

        public int EnrollmentID { get; set; }

        public int CourseID { get; set; }

        public int StudentID { get; set; }

        public Grade? Grade { get; set; }

       

        public virtual Course Course { get; set; }

        public virtual Student Student { get; set; }

    }

}

خاصیت EnrollmentID کلید اصلی (primary key) خواهد بود؛ این entity بجای ID به تنهایی، از الگوی classnameIDاستفاده می کند، همان طور که در موجودیت Student مشاهده گر آن بودید. به طور معمول یک الگو را انتخاب می کنیم و آن را در کل data model خود بکار می بریم. در اینجا، تغییر کوچکی که مشاهده کردید، نشانگر این است که می توان از هر دو الگو استفاده کرد.

خاصیت Grade ورودی از نوع شمارشی (enum) می پذیرد. علامت سوال پس از تعریف نوع Grade، بر این قضیه اشاره دارد که خاصیت Grade، nullable می باشد. لازم به ذکر است یک نمره (grade) که null یا تهی می باشد، از نمره ی صفر کاملا متفاوت است – null بیانگر این است که آن grade تعریف نشده یا هنوز مقداری به آن تخصیص نیافته است.

خاصیت StudentID یک کلید خارجی است و navigation property متناظر با آن Student می باشد. یک entity یا موجودیت Enrollment به یک Student مربوط می باشد، بنابراین خاصیت مورد نظر تنها می تواند یک موجودیتStudent را نگه دارد (بر خلاف Student.Enrollments navigation property که کمی پیشتر مشاهده کردید که قادر است چندین موجودیت Enrollment نگه دارد.)

خاصیت CourseID یک کلید خارجی است و navigation property مربوط با آن نیز Course می باشد. یک موجودیتEnrollment تنها به یک موجودیت Course مربوط یا متصل می باشد.

EF، در صورتی که خاصیتی <navigation property name><primary key property name> نام گذاری شده باشد، آن خاصیت را به عنوان یک خاصیت کلید خارجی (foreign key property) تفسیر می کند (به عنوان مثال، StudentID برایStudent navigation property زیرا که کلید اصلی موجودیت Student، ID می باشد). همین کار را می توان برای خاصیت های کلید خارجی (Foreign key properties) نیز انجام داد، <primary key property name> (به عنوان مثال، CourseIDزیرا که کلید اصلی موجودیتCourse ، CourseIDمی باشد ).

 

 

image

 

 

در پوشه ی Models، Course.cs را ایجاد کرده و کد template را با کد زیر جایگزین کنید:

using System.Collections.Generic;

using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models

{

    public class Course

    {

        [DatabaseGenerated(DatabaseGeneratedOption.None)]

        public int CourseID { get; set; }

        public string Title { get; set; }

        public int Credits { get; set; }

        public virtual ICollection<Enrollment> Enrollments { get; set; }

    }

}

خاصیت Enrollments یک navigation property می باشد. یک موجودیت Course ممکن است به چندین موجودیتEnrollment مربوط باشد.

بعده ها درباره ی خصیصه ی DatabaseGenerated بیشتر بحث خواهیم کرد. خصیصه ی نام برده اساسا به شما اجازه می دهد بجای اینکه کاری کنید پایگاه داده کلید اصلی را خود بسازد آن را برای course مورد نظر وارد نمایید.

ایجاد Database Context

کلاس اصلی که قابلیت EF را برای یک data model معین هماهنگ سازی می کند، کلاس database context است. کلاس ذکر شده را با ارث بری از کلاس System.Data.Entity.DbContext ایجاد می کنیم. در کد خود مشخص می کنیم کدامentity ها در data model گنجانده شوند، حتی می توانید برخی از رفتارهای EF را سفارشی تنظیم کنید. در این پروژه اسم کلاس را SchoolContext انتخاب می کنیم.

به منظور ایجاد یک پوشه در پروژه ی ContosoUniversity، بر روی پروژه در پنجره ی Solution Explorer راست کلیک کرده و Add را کلیک کنید. سپس بر روی New Folder کلیک نمایید. پوشه ی جدید را DAL (Data Access Layer) نام گذاری کنید. در آن پوشه یک فایل کلاس جدید به نام SchoolContext.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید:

    using ContosoUniversity.Models;

    using System.Data.Entity;

    using System.Data.Entity.ModelConfiguration.Conventions;

 

    namespace ContosoUniversity.DAL

    {

        public class SchoolContext : DbContext

        {

            public SchoolContext()

                : base("SchoolContext")

            {

            }

            public DbSet<Student> Students { get; set; }

            public DbSet<Enrollment> Enrollments { get; set; }

            public DbSet<Course> Courses { get; set; }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)

            {

                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            }

        }

    }

تعریف entity set ها (مجموعه ای از جداول)

این کد یک خاصیت DbSet ویژه ی هر entity set ایجاد می کند. در EF منظور از entity set همان جدول در پایگاه داده وentity نیز یک سطر یا ردیف از جدول است.

اگر دستورهای DbSet < Enrollment>و DbSet<Course> را هم حذف کنید باز در روند اجرا هیچ تغییر اتفاق نمی افتاد.EF آن ها را به صورت ضمنی مورد ارجاع قرار می داد (اضافه می کرد)، به این ترتیب که موجودیت Student به موجودیتEnrollment اشاره می کند و موجودیت Enrollment نیز به موجودیت Course اشاره می کند.

تعریف connection string

اسم connection string (که بعدا آن را به فایل Web.config اضافه خواهیم کرد) به constructor ارسال می شود.

    public SchoolContext() : base("SchoolContext")

{

}

همچنین می توانستید بجای اسم connection string که در فایل Web.config ذخیره می شود، خود connection stringرا به constructor ارسال نمایید.

اگر یک connection string معین یا اسم connection string را به صورت صریح تعریف نکنید، EF فرض می گیرد که اسمconnection string با اسم کلاس یکی است. اسم پیش فرض connection string در این مثال، SchoolContext خواهد بود، یکسان با آنچه به صورت صریح تعریف می کنید. 

تعریف اسامی جدول به صورت فردی و جمعی

دستور modelBuilder.Conventions.Remove در متد OnModelCreating مانع از این می شود که اسامی جدول به صورت جمعی تعریف شوند. اگر این کار نمی کردیم، جداول ایجاد شده به ترتیب Students، Courses و Enrollmentsنام گذاری می شدند. با استفاده از این دستور، اسامی جداول Student، Course و Enrollment به صورت فردی و بدون sجمع نام گذاری شده اند. برنامه نویسان در رابطه با اینکه آیا اسم جداول به صورت جمعی تعریف شوند یا فردی، اختلاف نظر دارند. در مقاله ی حاضر از اسم فردی برای جداول بهره گرفته شده، اما شما می توانید مطابق میل خود با اضافه یا حذف کردن این خط کد، اسم جدول را فرد یا جمع تعریف کنید.

   تنظیمEF  جهت مقداردهی اولیه پایگاه داده با داده های آزمایش

EF قادر است هنگامی که برنامه اجرا می شود به صورت خودکار یک پایگاه داده را ایجاد (یا حذف و مجدد ایجاد) کند. این امکان برای شما وجود دارد که مشخص کنید آیا هر بار که برنامه اجرا می شود، پایگاه داده خودکار ایجاد گردد یا فقط زمانی که model با پایگاه داده ی موجود همگام نیست، این اتفاق رخ دهد. همچنین می توانید یک متد Seed بنویسید که EFخودکار پس از ایجاد کردن پایگاه داده صدا می زند و به وسیله آن پایگاه داده ی مورد نظر را با داده های آزمایشی پر می کند.

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

در پوشه ی DAL، یک فایل کلاس جدید به نام SchoolInitializer.cs ایجاد کرده و کد template را با کد زیر جایگزین کنید. این کار باعث می شود پایگاه داده در صورت نیاز ایجاد شده و داده های آزمایشی در پایگاه داده ی جدید بارگذاری شوند.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Data.Entity;

using ContosoUniversity.Models;

namespace ContosoUniversity.DAL

{

    public class SchoolInitializer : System.Data.Entity. DropCreateDatabaseIfModelChanges<SchoolContext>

    {

        protected override void Seed(SchoolContext context)

        {

            var students = new List<Student>

            {

            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-0901")},

            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},

            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},

            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},

            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},

            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}

            };

            students.ForEach(s => context.Students.Add(s));

            context.SaveChanges();

            var courses = new List<Course>

            {

            new Course{CourseID=1050,Title="Chemistry",Credits=3,},

            new Course{CourseID=4022,Title="Microeconomics",Credits=3,},

            new Course{CourseID=4041,Title="Macroeconomics",Credits=3,},

            new Course{CourseID=1045,Title="Calculus",Credits=4,},

            new Course{CourseID=3141,Title="Trigonometry",Credits=4,},

            new Course{CourseID=2021,Title="Composition",Credits=3,},

            new Course{CourseID=2042,Title="Literature",Credits=4,}

            };

            courses.ForEach(s => context.Courses.Add(s));

            context.SaveChanges();

            var enrollments = new List<Enrollment>

            {

            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},

            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},

            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},

            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},

            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},

            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},

            new Enrollment{StudentID=3,CourseID=1050},

            new Enrollment{StudentID=4,CourseID=1050,},

            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},

            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},

            new Enrollment{StudentID=6,CourseID=1045},

            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},

            };

            enrollments.ForEach(s => context.Enrollments.Add(s));

            context.SaveChanges();

        }

    }

}

متد Seed، شی database context را به عنوان پارامتر ورودی می پذیرد، کد داخل متد به وسیله ی آن شی entity های جدید را به پایگاه داده اضافه می کند. به ازای هر entity type، کد یک مجموعه ی جدید از entity ها را ایجاد کرده و آن ها را به خاصیت DbSet مربوطه اضافه می کند، سپس تغییرات ایجاد شده را در پایگاه داده ذخیره می کند. ضرورتی ندارد متد SaveChanges را بعد از هر مجموعه entity (همان گونه که در این آموزش صورت گرفته) فراخوانی کرد. با این حال، انجام آن به شما کمک می کند در صورت رخداد خطا زمانی که کد در حال نوشته شدن در پایگاه داده هست، منشا یک مشکل را شناسایی کنید.

برای اینکه به EF دستور دهید از initializer class شما استفاده کند، یک المان را به عنصر entityFramework در فایلWeb.config (موجود در root folder پروژه) اضافه نمایید:

  <entityFramework>

  <contexts>

    <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">

      <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />

    </context>

  </contexts>

  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">

    <parameters>

      <parameter value="v11.0" />

    </parameters>

  </defaultConnectionFactory>

  <providers>

    <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />

  </providers>

</entityFramework>

context type اسم کلاس context که به صورت کامل تعریف شده را به همراه assembly ای که در آن جای گرفته مشخص می کند. databaseinitializer type اسم کلاس initializer که به طور کامل تعریف شده را به همراه assembly ای که در آن قرار گرفته، مشخص می کند. (اگر نمی خواهید که EF از initializer استفاده کند، می توانید خصیصه ی disableDatabaseInitialization="true"را بر روی المان context تعریف کنید)

یک روش جایگزین برای تنظیم initializer در فایل Web.config، تنظیم آن در کد با اضافه کردن یک دستورDatabase.SetInitializer به متد Application_Start در فایل Global.asax.cs است.

اکنون برنامه به گونه ای تنظیم شده، که هنگامی که شما برای بار نخست در یکبار اجرای برنامه به پایگاه داده دسترسی پیدا می کنید، EF پایگاه داده را با model (SchoolContext و کلاس های entity) مقایسه می کند و در صورت برخورد با هر گونه تفاوت بین این دو، پایگاه داده را حذف کرده و آن را مجدد ایجاد می کند.

توجه: هنگامی که شما برنامه را روی web server تولیدی خود مستقر می کنید، بایستی کدی را که پایگاه داده را حذف و بازسازی می کند، غیر فعال نمایید.

تنظیم EF برای استفاده از یک نسخه ی LocalDB پایگاه داده ی SQL Server Express

LocalDB یک نسخه ی کم حجم از موتور پایگاه داده ی SQL Server Express است. نصب و پیکربندی آن بسیار ساده می باشد، به مجرد تقاضا و بنا به درخواست آغاز شده و در حالت user mode اجرا می شود. LocalDB در یک حالت اجرایی ویژه از SQL Server Express اجرا می شود که به شما این امکان را می دهد، با پایگاه های داده مانند فایل های .mdf برخورد کنید.

اگر می خواهید پایگاه داده را همراه با پروژه کپی کنید، می توانید فایل های پایگاه داده ی LocalDB را در پوشه یApp_Data  یک پروژه ی وب جای گذاری نمایید. امکان user instance در SQL Server Express نیر به شما اجازه می دهد با فایل های .mdf کار کنید، اما استفاده از این امکان توصیه نمی شود، بنابراین تنها LocalDB مناسب کار با فایل های.mdf می باشد. در ویرایش 2012 و جدیدتر Visual Studio، LocalDB به صورت پیش فرض توسط خود محیط نصب می شود.

به طور معمول SQL Server Express، به خصوص نسخه ی LocalDB آن برای برنامه های تولیدی تحت وب (production web applications) مورد استفاده قرار نمی گیرد (و برای کار با برنامه های تحت وب مناسب نمی باشد)، زیرا که نسخه ی ذکر شده اساسا برای کار با IIS طراحی نشده.

در این آموزش با LocalDB کار خواهیم کرد. فایل برنامه ی Web.config را باز کرده و یک المان connectionStrings پیش از المان appSettings اضافه نمایید. (فایل Web.config را حتما در root folder پروژه بروز رسانی کنید. البته یک فایلWeb.config دیگر در زیرپوشه ی Views وجود دارد که نیاز به بروز رسانی آن نیست.)

در صورت استفاده از Visual Studio 2015، لازم است به این خاطر که اسم پیش فرض نمونه ی SQL Server تغییر یافته، "v11.0" را داخل connection string با "MSSQLLocalDB" جایگزین کنید.

<connectionStrings>

  <add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity1;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>

</connectionStrings>

<appSettings>

  <add key="webpages:Version" value="3.0.0.0" />

  <add key="webpages:Enabled" value="false" />

  <add key="ClientValidationEnabled" value="true" />

  <add key="UnobtrusiveJavaScriptEnabled" value="true" />

</appSettings>

 

Connection string ای که اضافه کردید، تعریف می کند که EF از یک پایگاه داده ی LocalDB به نامContosoUniversity1.mdf استفاده کند.(پایگاه داده ای هنوز ایجاد نشده؛ ولی EF آن را ایجاد می کند.) اگر می خواستید پایگاه داده در پوشه ی App_Data ایجاد شود، در آن صورت می بایستAttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf را به connection string اضافه می کردید. 

لزومی ندارد در فایل Web.config، یک connection string ایجاد کنید. در صورت فراهم نکردن connection string، EF بر اساس کلاس context شما، از یک connection string پیش فرض استفاده می کند.

ایجاد یک controller و views به نام Student

اکنون یک صفحه ی وب خواهیم ساخت که داده های ما را نمایش می دهد، فرایند درخواست داده به صورت خودکار پروسه ی ساخت پایگاه داده را فعال می کند. کار خود را با ایجاد یک controller آغاز خواهیم کرد. اما پیش از آن باید پروژه را کامپایل کرده (build) تا کلاس های model و context در اختیار MVC controller scaffolding قرار گیرد.

1.     بر روی پوشه ی Controllers در Solution Explorer راست کلیک کرده، Add را انتخاب کنید، سپس New Scaffolded Item را کلیک نمایید.

2.     در پنجره ی محاوره ی Add Scaffold، MVC 5 Controller with views, using Entity Framework را انتخاب نمایید.

 

 

image

 

 

3.     در پنجره ی محاوره ی Add Controller، به ترتیب زیر اقدام کنید:

Model class: Student (ContosoUniversity.Models )

Data context class: SchoolContext (ContosoUniversity.DAL )

Controller name: StudentController

مقادیر فیلدهای دیگر را تغییر ندهید.

 

 

 

 

image

 

 

هنگامی که بر روی Add کلیک می کنید، scaffolder یک فایل StudentController.cs و مجموعه ای از view ها (فایل های.cshtml) را ایجاد می کند که با controller کار می کنند. در پروژه هایی که در آینده ایجاد می کنید و در آن ها از EF استفاده می کنید، می توانید از تعدادی قابلیت اضافی scaffolder بهره بگیرید: کافی است اولین کلاس model خود را ایجاد کرده، سپس در کادر Add Controller، یک کلاس context جدید تعریف کنید(در این مرحله از تعریف connection stringخودداری نمایید). Scaffolder خود کلاس DbContext و connection string را به ضمیمه ی controller و view ها ایجاد می کند. 

4.     Visual Studio، فایل Controllers\StudentController.cs را باز می کند. خواهید دید که یک class variableاضافه شده که database context object را مقداردهی اولیه می کند:

private SchoolContext db = new SchoolContext();

متد اکشن Index یک لیست از دانشجویان را از entity set به نام Students بازیابی می کند. این کار با خواندن خاصیتStudents از نمونه ی database context صورت می گیرد:

         public ViewResult Index()

{

    return View(db.Students.ToList());

}

Student\Index.cshtml view ، این لیست را در یک جدول نمایش می دهد:

<table>

    <tr>

        <th>

            @Html.DisplayNameFor(model => model.LastName)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.FirstMidName)

        </th>

        <th>

            @Html.DisplayNameFor(model => model.EnrollmentDate)

        </th>

        <th></th>

    </tr>

 

    @foreach (var item in Model)

    {

        <tr>

            <td>

                @Html.DisplayFor(modelItem => item.LastName)

            </td>

            <td>

                @Html.DisplayFor(modelItem => item.FirstMidName)

            </td>

            <td>

                @Html.DisplayFor(modelItem => item.EnrollmentDate)

            </td>

            <td>

                @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |

                @Html.ActionLink("Details", "Details", new { id = item.ID }) |

                @Html.ActionLink("Delete", "Delete", new { id = item.ID })

            </td>

        </tr>

    }

</table>

       

2.     CTRL+F5 را زده تا پروژه اجرا شود. (در صورت برخورد با خطای "Cannot create Shadow Copy"، مرورگر را بسته و مجددا امتحان کنید.)

روی تب Students کلیک کرده تا داده هایی که توسط متد Seed درج گردیده را مشاهده نمایید. اگر پنجره ی مرورگر باریک بود، باید بر گوشه ی بالا، سمت راست کلیک کنید و یا در صورت بزرگ بودن پنجره، می توانید لینک تب Studentsرا در نوار آدرس بالای پنجره ببینید و انتخاب کنید.

 

 

image

 

 

 

image

 

مشاهده ی پایگاه داده

هنگامی که صفحه ی Students را اجرا کردید و برنامه سعی کرد به پایگاه داده دسترسی پیدا کند، EF متوجه می شود که پایگاه داده ای ایجاد نشده، بنابراین خود یک پایگاه داده ایجاد کرده، سپس با اجرا کردن متد seed پایگاه داده را با داده های آزمایشی پر می کند.

برای مشاهده ی پایگاه داده در محیط Visual Studio، می توان از Server Explorer یا SQL Server Object Explorerاستفاده کرد. در این آموزش از Server Explorer استفاده خواهیم کرد (در نسخه های پیش از 2013، Server Explorer،Database Explorer خوانده می شود.)

1.     مرورگر را ببندید.

2.     در پنجره ی Server Explorer، Data Connections => School Context (ContosoUniversity) و سپس Tables را باز کرده تا جداول را در پایگاه داده ی جدید خود مشاهده کنید:

 

 

image

 

 

3.     روی جدول Student راست کلیک کرده و بر روی Show Table Data کلیک کنید تا ستون هایی که ایجاد شده و سطرهایی که در جدول درج گردیده را مشاهده کنید.

 

image

 

 

4.     اتصال Server Explorer را قطع کنید.

فایل های ContosoUniversity1.mdf و .ldf در پوشه ی C:\Users\yourusername>> قرار دارند.

به این خاطر که شما از DropCreateDatabaseIfModelChanges initializer استفاده می کنید، می توانید تغییراتی را به کلاس Student اعمال نمایید، حال برنامه را مجدد اجاره کنید، خواهید دید که پایگاه داده به صورت خودکار مجدد ایجاد شده و خود را با تغییراتی که شما اعمال کرده اید، مطابق می کند. به عنوان مثال، اگر خاصیت EmailAddress را به کلاسStudent اضافه کنید و صفحه ی students را مجدد اجرا کنید، سپس به جدول مورد نظر مراجعه کنید، خواهید دید که یک ستون جدید به نام EmailAddress اضافه شده است.

مقدار کدی که بایستی می نوشتید تا EF بتواند یک پایگاه داده ی کامل را ایجاد کند، به دلیل وجود قرارداد ها (convention ها) بسیار کم بود. متوجه برخی از آن ها شدید و برخی هم گونه ای بودند که از وجود و اجرای آن ها آگاه نبودید:

1.     صورت جمع اسم های کلاس entity که به عنوان اسم جداول مورد استفاده واقع شدند.

2.     اسم های property های entity که برای اسم ستون بکار برده شدند.

3.     خاصیت های entity که ID یا classnameID نام گذاری شدند و به عنوان خاصیت های primary key شناخته می شوند.

4.     یک خاصیت زمانی به عنوان foreign key در نظرگرفته می شوند که بدین صورت نام گذاری شده باشد<navigation property name><primary key property name> (به عنوان مثال، می توان به StudentID برایStudent navigation property اشاره کرد، زیرا که کلید اصلی موجودیت Student، ID می باشد). خواص foreign key را نیز می توان به همان شیوه نام گذاری کرد <primary key property name>. (به عنوان مثال،EnrollmentID زیرا که کلید اصلی موجودیت Enrollment،  EnrollmentIDمی باشد).

همچنین مشاهده کردید که قرار دادها را می توان باطل کرده و بازنویسی کرد. برای مثال، تعیین کردید که اسم جداول به صورت جمع تعریف نشوند.

چکیده

در این درس یک برنامه ی ساده ایجاد کردید با بهره گیری از تکنولوژی EF و نسخه ی LocalDB اس کیو ال سرور اکسپرس داده ها را ذخیره کرده و به نمایش گذاشت. در مبحث بعدی با نحوه ی انجام عملیات ساده CRUD آشنا خواهید شد.

منبع وب سایت تحلیل داده

سه شنبه 19 آبان 1394  7:45 AM
تشکرات از این پست
دسترسی سریع به انجمن ها