سلام خدمت دوستان عزیز و همراهان گرامی حالتون چطوره ؟امیدوارم که روزی خوب را درپیش رو داشته  باشید.با یکی دیگر از اموزشهای mvc در خدمتتون هستم امیدد است که این مطالب برای شما راه گشا  در امر برنامه نویسی باشد.امروز میخوام در مورد ایجاد کنترل کننده ی instructor و ویوها صحبت کنیم. با ما همراه باشید..

یک کنترل کننده ی InstructorController با عملکردهای خواندن / نوشتن EF ایجاد کنید، همانطور که در تصویر زیر مشاهده می کنید:

Controllers\InstructorController.cs  را باز کرده و یک عبارت using  برای فضا نام ViewModels اضافه کنید:

using ContosoUniversity.ViewModels;‎

کد scaffolded در روش Index  بارگذاری سریع را فقط برای پراپرتی مسیریابی OfficeAssignment  تعیین می کند.

public ActionResult Index()‎

‎{‎

‎    var instructors = db.Instructors.Include(i => i.OfficeAssignment);‎

‎    return View(instructors.ToList());‎

‎}‎

کد زیر را جایگزین روش Index   کنید تا  داده های مرتبط افزوده بارگذاری کرده و آن را در مدل ویو قرار دهید.

public ActionResult Index(int? id, int? courseID)‎

‎{‎

‎    var viewModel = new InstructorIndexData();‎

‎    viewModel.Instructors = db.Instructors

‎        .Include(i => i.OfficeAssignment)‎

‎        .Include(i => i.Courses.Select(c => c.Department))‎

‎        .OrderBy(i => i.LastName);‎

‎    if (id != null)‎

‎    {‎

‎        ViewBag.InstructorID = id.Value;‎

‎        viewModel.Courses = viewModel.Instructors.Where(‎

‎            i => i.ID == id.Value).Single().Courses;‎

‎    }‎

‎    if (courseID != null)‎

‎    {‎

‎        ViewBag.CourseID = courseID.Value;‎

‎        viewModel.Enrollments = viewModel.Courses.Where(‎

‎            x => x.CourseID == courseID).Single().Enrollments;‎

‎    }‎

‎    return View(viewModel);‎

‎}‎

روش مسیرهای انتخابی داده (id)   و یک رشته ردیف را نی پذیرد (courseID)  که مقادیر ID مدرس انتخاب شده و واحد انتخابی را ارائه می دهد و همه ی داده های مورد نیاز را به ویو انتقال می دهد. پارامترها توسط هایپرلینک Select  روی صفحه ارائه می شوند. کد با ایجاد نمونه ای از ویو و قرار دادن آن در لیست مدرسین شروع می شود. کد بارگذاری سریع را برای پراپرتی مسیریابی Instructor.OfficeAssignment  و Instructor.Courses تعیین می کند.

var viewModel = new InstructorIndexData();‎

viewModel.Instructors = db.Instructors

‎    .Include(i => i.OfficeAssignment)‎

‎    .Include(i => i.Courses.Select(c => c.Department))‎

‎     .OrderBy(i => i.LastName);‎

روش دوم Include واحدها را بارگذاری می کند و برای هر واحد که بارگذاری می شود، بار گذاری سریع را برای پراپرتی مسیریابی theCourse.Department  انجام می دهد.

‎.Include(i => i.Courses.Select(c => c.Department))‎

همانطور که قبلا ذکر شد، بارگذاری سریع ضروری نیست اما برای بهبود اجرا انجام می شود. از آنجایی که ویو همیشه ماهیت OfficeAssignment  را لازم دارد، موثرتر است که آن را در همان ردیف وارد کنیم. وقتی که در صفحه ی وب یک مدرس انتخاب می شود، ماهیت های Course  لازم می باشند. بنابراین فقط اگر صفحه با یک واحد انتخابی بیشتر نمایش داده می شود، تا بدون آن، بارگذاری سریع بهتر از بارگذاری آهسته می باشد.

اگر ID یک مدرس انتخاب شده باشد، مدرس انتخابی از لیست مدررسین در مدل ویو بازگردانده می شود. مدل ویو مربوط به پراپرتی Courses  با ماهیت های Course از پراپرتی مسیریابی Courses   مربوط به مدرسین بارگذاری می شود.

if (id != null)‎

‎{‎

‎    ViewBag.InstructorID = id.Value;‎

‎    viewModel.Courses = viewModel.Instructors.Where(i => i.ID == ‎id.Value).Single().Courses;‎

‎}‎

روش Where  مجموعه ای را گزارش می دهد، اما در این مورد معیارها فقط در یک ماهیت مجزای Instructor به آن روش انتقال داده می شوند. روش Single مجموعه را به یک روش مجزای Instructor تغییر می دهد که برای شما دسترسی به ماهیت پراپرتی Courses را فراهم می کند. وقتی که می دهنید مجموعه فقط یک آیتم خواهد داشت از روش Singleاستفاده خواهید کرد. اگر مجموعه ی انتقال داده شده خالی باشد و یا اینکه بیشتر از یک آیتم وجود داشته باشد، این روش یک اکسپشن به وجود می آورد. SingleOrDefault یک انتخاب می باشد که اگر مجموعه خالی باشد، مقدار پیش فرض را گزارش می دهد. به هرحال در این مورد نتیجه در یک اکسپشن می باشد که پیغام اکسپشن دلیل مشکل را با وضوح کمتری نشان می دهد. وقتی که روش Single  را فرا می خوانید، به جای فراخوانی مجزای روش Where  می توانید به روش Where  نیز انتقال دهید.

‎.Single(i => i.ID == id.Value)‎

به جای:

‎.Where(I => i.ID == id.Value).Single()‎

سپس اگر یک واحد انتخاب شده باشد، واحد انتخابی از لیست واحدها در مدل ویو بازیابی می شود. بنابراین مدل ویو پراپرتی Enrollments  با ماهیت های Enrollment از  پراپرتی مسیریابی Enrollments بارگذاری می شود.

‎    if (courseID != null)‎

‎    {‎

‎        ViewBag.CourseID = courseID.Value;‎

‎        viewModel.Enrollments = viewModel.Courses.Where(‎

‎            x => x.CourseID == courseID).Single().Enrollments;‎

‎    }‎

تغییر شاخص ویو Instructor:

در Views\Instructor\Index.cshtml کد زیر را جایگزین کد الگو کنید، تغییرات مشخص شده اند.

@model ContosoUniversity.ViewModels.InstructorIndexData

@{‎

‎    ViewBag.Title = “Instructors”;‎

‎}‎

‎<h2>Instructors</h2>‎

‎<p>

‎    @Html.ActionLink(“Create New”, “Create”)‎

</p>‎

‎<table class=”table”>

<tr>

<th>Last Name</th>‎

<th>First Name</th>‎

<th>Hire Date</th>‎

<th>Office</th>‎

<th></th>‎

</tr>‎

‎    @foreach (var item in Model.Instructors)‎

‎    {‎

‎        string selectedRow = “”;‎

‎        if (item.ID == ViewBag.InstructorID)‎

‎        {‎

‎            selectedRow = “success”;‎

‎        }‎

<tr class=”@selectedRow”>

<td>  @Html.DisplayFor(modelItem => item.LastName)‎    </td>‎

<td>  @Html.DisplayFor(modelItem => item.FirstMidName)‎</td>‎

<td>   @Html.DisplayFor(modelItem => item.HireDate)   ‎</td>‎

<td>

‎                @if (item.OfficeAssignment != null)‎

‎                {‎

‎                    @item.OfficeAssignment.Location

‎                }‎

</td>‎

<td>

‎                @Html.ActionLink(“Select”, “Index”, new { id = item.ID }) |‎

‎                @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>‎

شما تغییرات زیر را در کد موجود اعمال کرده اید:

·         تغییر مدل گروه به InstructorIndexData.

·         تغییر تیتر صفحه از Index به  Instructors.

·         افزودن یک ستون Office که item.OfficeAssignment.Location  را فقط اگر item.OfficeAssignment بی اثر باشد، نمایش می دهد. ( زیرا این یک رابطه ی یک به صفر یا یک می باشد، یک ماهیت مرتبط OfficeAssignment وجود ندارد.)

‎<td>

‎    @if (item.OfficeAssignment != null) ‎

‎    { ‎

‎        @item.OfficeAssignment.Location  ‎

‎    } ‎

</td> ‎

·         کد افزوده شده که به طور پویا class=”success” را به عنصر tr از مدرس انتخاب شده اضافه می کند.

string selectedRow = “”; ‎

if (item.InstructorID == ViewBag.InstructorID) ‎

‎{ ‎

‎    selectedRow = “success”; ‎

‎}

<tr class=”@selectedRow” valign=”top”> ‎

·         یک ActionLink جدید با نام Select فورا قبل از لینک های دیگر در هر ردیف وارد شده که باعث می شود ID مدرس انتخاب شده به روش Index ارسال شود.

برنامه را اجرا کرئه و تب Instructors را انتخاب کنید. وقتی هیچ ماهیت OfficeAssignment  مرتبطی وجود نداشته باشد، صفحه پراپرتی  Location  از ماهیت های OfficeAssignment  و یک سلول خالی جدول را نمایش می دهد.

image

در فایل Views\Instructor\Index.cshtml  پس از بستن عنصر table  (در انتهای فایل)، کد زیر را وارد کنید. این کد لیستی از واحدهای مرتبط به یک مدرس انتخابی را نمایش می دهد:

@if (Model.Courses != null)‎

‎{‎

‎    <h3>Courses Taught by Selected Instructor</h3>‎

‎    <table class=”table”>

‎    ‎

<tr>

‎        ‎

<th></th>‎

<th>Number</th>‎

<th>Title</th>‎

<th>Department</th>‎

</tr>‎

‎        @foreach (var item in Model.Courses)‎

‎        {‎

‎            string selectedRow = “”;‎

‎            if (item.CourseID == ViewBag.CourseID)‎

‎            {‎

‎                selectedRow = “success”;‎

‎            }‎

<tr class=”@selectedRow”>

<td> @Html.ActionLink(“Select”, “Index”, new { courseID = item.CourseID })‎ </td>‎

<td>   @item.CourseID          </td>‎

<td>   @item.Title             </td>‎

<td>   @item.Department.Name   </td>‎

</tr>‎

‎        }‎

</table>‎

‎}‎

این کد پراپرتی Courses از مدل ویو را می خواند تا لیستی از واحدها را نمایش دهد. همچنین یک هایپرلینک Select ارائه می دهد که ID واحد انتخاب شده را به روش عملکرد Index  می فرستد.

صفحه را اجرا کرده و یک مدرس انتخاب کنید. اکنون یک چارچوب می بینید که واحدهای اختصاص داده شده به مدرس انتخابی را نمایش می دهد و برای هر واحد نام دپارتمان اختصاص داده شده را مشاهده می کنید.

image

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

@if (Model.Enrollments != null)‎

‎{‎

‎    <h3>  Students Enrolled in Selected Course  </h3>‎

‎    <table class=”table”>

‎    ‎

<tr>

<th>Name</th>‎

<th>Grade</th>‎

</tr>‎     @foreach (var item in Model.Enrollments)‎{‎    <tr>

<td>   @item.Student.FullName                      </td>‎

<td>   @Html.DisplayFor(modelItem => item.Grade)‎   </td>‎

</tr>‎

‎        }‎

</table>‎

‎}‎

این کد پراپرتی Enrollments را از مدل ویو را می خواند برای اینکه لیستی از دانشجویان ثبت نام شده در واحد را نمایش دهد.

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

image

افزودن بارگذاری آشکارا:

InstructorController.cs  را باز کرده و دقت کنید که چگونه روش Index لیست ثبت نامی ها برای واحد انتخابی را ارائه می دهد:

‎    if (courseID != null)‎

‎    {‎

‎        ViewBag.CourseID = courseID.Value;‎

‎        viewModel.Enrollments = viewModel.Courses.Where(‎

‎            x => x.CourseID == courseID).Single().Enrollments;‎

‎    }‎

وقتی که لیست مدرسین را بازیابی می کنید، برای پراپرتی Courses مسیریابی و برای پراپرتی Department از هر واحد بارگذاری سریع را تعیین می کنید. سپس مجموعه ی Courses را در مدل ویوی قرار می دهید و اکنون از یک ماهیت در آن مجموعه به پراپرتی مسیریابی Enrollments دسترسی دارید. از آنجایی که برای پراپرتی مسیریابی Course.Enrollments  بارگذاری سریع را تعیین نکردید، داده ی مربوط به آن پراپرتی در صفحه به عنوان نتیجه ای از بارگذاری آهسته ظاهر می شود.

اگر شما بدون تغییر کد به هر روشی بارگذاری آهسته را غیرفعال کرده باشید، بدون توجه به تعداد ثبت نام هایی که هر واحد دارد، پراپرتی Enrollments پوچ خواهد بود. در این مورد برای بارگذاری پراپرتی  Enrollments  باید یا بارگذاری سریع یا بارگذاری آشکار را تعیین کنید. شما تقریبا چگونگی انجام بارگذاری سریع را مشاهده کرده اید. برای مشاهده ی مثالی مربوط به بارگذاری آشکار، کد زیر را جایگزین روش Index کنید که پراپرتیEnrollments را بارگذاری می کند. تغییرات مشخص شده اند:

public ActionResult Index(int? id, int? courseID)‎

‎{‎

‎    var viewModel = new InstructorIndexData();‎

‎    viewModel.Instructors = db.Instructors

‎        .Include(i => i.OfficeAssignment)‎

‎        .Include(i => i.Courses.Select(c => c.Department))‎

‎        .OrderBy(i => i.LastName);‎

‎    if (id != null)‎

‎    {‎

‎        ViewBag.InstructorID = id.Value;‎

‎        viewModel.Courses = viewModel.Instructors.Where(‎

‎            i => i.ID == id.Value).Single().Courses;‎

‎    }‎

‎    ‎

‎    if (courseID != null)‎

‎    {‎

‎        ViewBag.CourseID = courseID.Value;‎

‎        // Lazy loading

‎        //viewModel.Enrollments = viewModel.Courses.Where(‎

‎        //    x => x.CourseID == courseID).Single().Enrollments;‎

‎        // Explicit loading

‎        var selectedCourse = viewModel.Courses.Where(x => x.CourseID == ‎courseID).Single();‎

‎        db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();‎

‎        foreach (Enrollment enrollment in selectedCourse.Enrollments)‎

‎        {‎

‎            db.Entry(enrollment).Reference(x => x.Student).Load();‎

‎        }‎

‎        viewModel.Enrollments = selectedCourse.Enrollments;‎

‎    }‎

‎    return View(viewModel);‎

‎}‎

پس از به دست آوردن ماهیت انتخاب شده ی Course کد به طور آشکارا پراپرتی مسیریابی Enrollments را بارگذاری می کند.

db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();‎

سپس هر ماهیت Enrollment مربوط به ماهیت Student را بارگذاری می کند.

db.Entry(enrollment).Reference(x => x.Student).Load();‎

دقت کنید که شما از روش Collection برای بارگذاری پراپرتی مجموعه استفاده می کنید، اما برای یک پراپرتی که تنها یک ماهیت را در خود دارد از روش Reference استفاده می کنید.

اکنون صفحه ی Instructor Index  را اجرا کنید، هیچ تفاوتی در آنچه روی صفحه نمایش داده شده مشاهده نخواهید کرد، گرچه چگونگی بازیابی داده را تغییر داده اید.