ایمیل
admin [at] VaniaIT.Com
امور مشتریان
پرتال کاربران - CRM
تلفن
9122830795(98+)
طراحی وب سایت

آموزش Entity Framework 6 Code First – بخش سوم


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

برای شروع نیز با همان کلاس Students که اطلاعات داخلش داشتیم شروع می کنیم.

اضافه کردن تابع Sort به متد اکشن 

برای این منظور ابتدا کنترلر StudentsController.cs را که قبلاْ در فولدر Controller ایجاد کرده بودیم را باز می نماییم. در خط ۱۹ ویژوال استودی و جایی که متد Index شروع می شود کدهای زیر را جایگزین می نماییم

        private SchoolContext db = new SchoolContext();

        // GET: Students
        public ActionResult Index(string sortOrder)
        {
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
            ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
            var students = from s in db.Students
                           select s;
            switch (sortOrder)
            {
                case "name_desc":
                    students = students.OrderByDescending(s => s.LastName);
                    break;
                case "Date":
                    students = students.OrderBy(s => s.EnrollmentDate);
                    break;
                case "date_desc":
                    students = students.OrderByDescending(s => s.EnrollmentDate);
                    break;
                default:
                    students = students.OrderBy(s => s.LastName);
                    break;
            }
            return View(db.Students.ToList());
        }

یعنی باید شبیه شکل شماره ی ۲۹-۳ بشود

۰۲۹ شکل شماره ۳-۲۹

 

  حال نوبت ظاهر صفحه است. وارد ویو شده (مطابق شکل ۳۰-۳)

 

۰۳۰

شکل شماره ۳۰-۳

  و کدهای زیر را وارد می نماییم. یعنی به جای خطوط  ۱۳ الی ۲۴ در ویژوال استودیو خطوط زیر را جایگزین می نماییم  

 

<tr>
<th>
@Html.ActionLink("Last Name", "Index", new { sortOrder = 
ViewBag.NameSortParm })
</th>
<th>First Name
</th>
<th>
@Html.ActionLink("Enrollment Date", "Index", new { sortOrder = 
ViewBag.DateSortParm })
</th>
<th></th>
</tr>

یعنی باید کدهای ویو مانند زیر باشد

@model IEnumerable<VaniaUniversity.Models.Student>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.ActionLink("Last Name", "Index", new {sortOrder = ViewBag.NameSortParm})
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new {sortOrder = ViewBag.DateSortParm })
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </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>

قبل از اینکه به توضیحات بپردازیم ابتدا نگاهی به تغییرات می نماییم. پروژه را یکبار بیلد و سپس ران کنید و وارد صفحه دانشجویان شوید. همانطور که ملاحظه می کنید دو ستون نام و تاریخ لینک دار شده اند و شما چنانچه روی آنها کلیک کنید ، مرتب می شوند. (شکل ۳۱-۳)

 

۰۳۱

 

شکل شماره ۳۱-۳

  و حالا توضیحات کدهای قسمت کنترلر

 

  • در خط ۲۱ و ۲۲ ما برای sort کردن دو ستون خود، دو نوع داده معرفی کردیم که توسط Viewbag به صفحه پاس داده می شوند و در خطوط بعدی میاییم برای این دو ، تعاریف مخصوص به خود را می نویسیم
  • Sortorder پارامتری است که توسط کوئری های ارسال شده در URL فراخوانی و اجرا می شود. یعنی کوئری استرینگ است. Query String ها در MVC پارامترهایی در اکشن هستند که وظایف مختلفی را بر عهده دارند
  • در خط ۲۵ توسط دستور شرطی-حلقه اس Switch-case یک متغیر به نام sortOrder معرفی کردیم تا در خطوط بعدی از آن استفاده نماییم
  • در خطوط ۲۷ الی ۳۳ سه case یا مورد را برای شرط switch معرفی نمودیم که هرکدام مشخص هستند و عنوان کردیم که هر کدام را برایمان sortOrderکن در خط ۴۰ نیز گفتیم برایمان لیست دانشجویان را برگردان.
  • نکته ی مهمی که در این خطوط وجود دارد مبحثی است تحت عنوان IQueryable که از متدهای استفاده شده ی LINQ To Entity می باشد و میتوانید مفصل در این لینک به مطالعه بپردازید. مطمئناً بهترین منبع برای آموزش مفاهیم برنامه نویسی دات نت همین MSDN است ولی ما در اینجا قصد داریم تا به زبان محاوره ای بگوییم این IQueryable چیست. یک منبع داده ای داریم و قرار است این داده ها را ارزیابی کنیم، در برنامه نویسی دات نت ما از IQueryable کمک میگیریم. فرض کنید ما یک ظرف سیب داریم ، برای شمارش این سیب های درون ظرف باید قانونی وضع کنیم که مثلاً اگر یکی برداشته شد شمارش انجام شود، اگر همرو خوردیم دوباره شمارش انجام شود و یا اگر یکی اضافه کردیم … درباره LINQ To Entity نیز می توانید به این لینک مراجعه کنید
  • در قسمت View نیز کار خاصی نکردیم. فقط ستونهایی را که میخواستیم توسط دستور @Html.ActionLink  لینک دار کردیم و sortOrder را به اینجا معرفی و پاس دادیم

 

اضافه کردن فیلد جستجوی پیشرفته در MVC

 در ادامه نیز میخواهیم باکس جستجو برای هر بخش بگذاریم تا پیدا کردن مطلب مورد نظر راحت تر باشد. طبق روال همین آموزش یعنی آموزش Entity Framework 6 Code First – بخش سوم به سراغ کنترلر StudentController میرویم و مواردی را به اکشن Index آن اضافه می کنیم. یعنی ابتدا یک معرف به کل اکشن اضافه می کنیم تحت نام string searchString  و سپس خطوط زیر را به بدنه ی اکشن اضافه می نماییم

            if (!String.IsNullOrEmpty(searchString))
            {
                students = students.Where (s => s.LastName.ToUpper().Contains(searchString.ToUpper()) || s.FirstName.ToUpper().Contains(searchString.ToUpper());
            }

یعنی کدهای بخش اکشن Index باید شبیه کدهای زیر باشد

        public ActionResult Index(string sortOrder, string searchString)
        {
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
            ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
            var students = from s in db.Students
                           select s;
            if (!String.IsNullOrEmpty(searchString))
            {
                students = students.Where (s => s.LastName.ToUpper().Contains(searchString.ToUpper()) || s.FirstName.ToUpper().Contains(searchString.ToUpper());
            }
            switch (sortOrder)
            {
                case "name_desc":
                    students = students.OrderByDescending(s => s.LastName);
                    break;
                case "Date":
                    students = students.OrderBy(s => s.EnrollmentDate);
                    break;
                case "date_desc":
                    students = students.OrderByDescending(s => s.EnrollmentDate);
                    break;
                default:
                    students = students.OrderBy(s => s.LastName);
                    break;
            }
            return View(db.Students.ToList());
        }

و برای نمایش در ویو نیز باید تغییراتی را در فایل Index.Cshtml ویوی Student بدهیم

@using (Html.BeginForm())
{
    <p>
        جستجو بر اساس نام : @Html.TextBox("searchString")<input type="submit" value="Search" />
    </p>
}

یعنی کدهای View باید شبیه به کدهای زیر باشد

@model IEnumerable<VaniaUniversity.Models.Student>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm())
{
    <p>
        جستجو بر اساس نام : @Html.TextBox("searchString")<input type="submit" value="Search" />
    </p>
}

<table class="table">
    <tr>
        <th>
            @Html.ActionLink("نام", "Index", new {sortOrder = ViewBag.NameSortParm})
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new {sortOrder = ViewBag.DateSortParm })
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </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>

یکبار سیو و سپس بیلد می کنیم پروژه را تا شاهد نتیجه ی اعمالمان باشیم :دی

 

۰۳۲

شکل شماره ۳۲-۳

توضیحات قسمت Action و View به شرح زیر است

 

  • رشته ای به نام searchString به متد اکشن Index اضافه کردیم تا بتوانیم توسط دستور where -که از دستورات LINQ است- لیست دانشجویانی که نام یا نام خانوادگیشان شامل searchString است را بازگردانیم. یعنی این رشته کمک می کند تا لیستی از اسامی مشابه را که ما جستجو کردیم را نمایش دهد.
  • در قسمت ویو نیز یک تکس باکس ایجاد کردیم تا اطلاعات کاربر را گرفته و داده های مناسب را نمایش دهد. یعنی توسط @Html.TextBox("searchString") داده را از کاربر دریافت می کند و در رشته searchstring قرار می دهد تا اطلاعات مناسب را نمایش دهد

 

 اضافه کردن صفحه بندی به برنامه ی MVC.Net

در این بخش قرار است تا صفحه بندی را با یکدیگر به پیش ببریم. زمانی ممکن است تعداد داده های شما بیش از هزاران عدد برسد، نمی توان همه را در یک صفحه نمایش داد، برای همین احتیاج داریم تا در هر صفحه به عنوان مثال ده داده را نمایش دهیم. روش های زیادی برای این کار وجود دارد . روشی که ما در اینجا استفاده خواهیم کرد پیشنهاد خود مایکروسافت است، مایکروسافت برای صفحه بندی و مرتب سازی داده ها پکیجی را ارائه داده تحت نام  PagedList.Mvc که هم در سایت خود مایمروسافت موجود است و هم در گالری Nuget . این روش اجباری نیست و شما می توانید با کمی جستجو در اینترنت به راه های متنوع دیگری نیز دست پیدا کنید.

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

Install-Package PagedList.Mvc

سپس اینتر را میزنیم تا نصب شود. و در نهایت مطابق شکل زیر خواهد شد.

 

۰۳۳

شکل شماره ۳۳-۳

همچنین باید در قسمت ریفرنس ها نیز به مانند شکل زیر این دو اضافه شده باشند

 

۰۳۴

شکل شماره ۳۴-۳

[blockquote author="NuGet Gallery" source="https://www.nuget.org/packages/PagedList.Mvc/" style="s1"]جهت اطلاع از آخرین نسخه ی PagedList.Mvc می توانید به گالری این پکیج در Nuget و این آدرس مراجعه نمایید. در حال حاضر نسخه ۴٫۵٫۰ موجود می باشد[/blockquote]  

این پکیج به عنوان مجموعه ای از pagedList میباشد که اکستنشن متدهای بسیار پرکاربردی همچون IQueryable و IEnumerable را در خود جای داده است. که در هر صفحه ای که از این پکیج استفاده می کنیم خصوصیات اکستنشن متدهای نام برده شده را برای داده های آن صفحه معرفی و استفاده می نماید. یعنی به هر صفحه به صورت مجزا کمک می کند تا به کمک این اکستنشن متدها صفحه را بارگزاری نماید.

حال برسیم سراغ تعریف توابع در کنترلر. ابتدای فضای نامی زیر را اضافه می کنیم

using PagedList;

و سپس در همان اکشن یعنی در اکشن Index مربوط به کنترلر StudentController کدهای زیر را جایگزین می کنیم

        public ActionResult Index(string sortOrder, string searchString, string currentFilter, int? page)
        {
            ViewBag.CurrentSort = sortOrder;
            ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
            ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

            if (searchString != null)
            {
                page = 1;
            }
            else
            {
                searchString = currentFilter;
            }
            ViewBag.CurrentFilter = searchString;

            var students = from s in db.Students select s;
            if (!String.IsNullOrEmpty(searchString))
            {
                students = students.Where (s => s.LastName.ToUpper().Contains(searchString.ToUpper()) || s.FirstName.ToUpper().Contains(searchString.ToUpper()));
            }
            switch (sortOrder)
            {
                case "name_desc": students = students.OrderByDescending(s => s.LastName);
                    break;
                case "Date": students = students.OrderBy(s => s.EnrollmentDate);
                    break;
                case "date_desc": students = students.OrderByDescending(s => s.EnrollmentDate);
                    break;
                default:
                    students = students.OrderBy(s => s.LastName);
                    break;
            }
            int pageSize = 3;
            int pageNumber = (page ?? 1);
            return View(students.ToPagedList(pageNumber, pageSize));
        }

و در قسمت ویو نیز کدهای زیر را اضافه و جایگزین می نماییم

@model PagedList.IPagedList<VaniaUniversity.Models.Student>
@using PagedList.Mvc;

@*@model IEnumerable<VaniaUniversity.Models.Student>*@

@{
    ViewBag.Title = "لیست دانشجویان";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("ثبت دانشجوی جدید", "Create")
</p>
@using (Html.BeginForm("Index","Student", FormMethod.Get))
{
    <p>
        جستجو بر اساس نام : @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)<input type="submit" value="Search" />
    </p>
}

<table class="table">
    <tr>
        <th>
            @Html.ActionLink("نام", "Index", new {sortOrder = ViewBag.NameSortParm})
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new {sortOrder = ViewBag.DateSortParm })
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </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>

<br/>
صفحه  @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) از @Model.PageCount
@Html.PagedListPager(Model, page => Url.Action("Index", new { page , sortOrder = ViewBag.CurrentSort , currentFilter = ViewBag.CurrentFilter }))

در نهایت پس از ذخیره و بیلد کردن پروژه تغییرات را مشاهده خواهید کرد

 

۰۳۵

 

شکل شماره ۳۵-۳

 

۰۳۶

شکل شماره ۳۶-۳

توضیحات کدهای بالا

  • در خط شماره ۲۰ کنترلر ما دو پارامتر استاتیک دیگر را تعریف کردیم که یکی از نوع int است برای شمارش صفحات و دیگری نیز از نوع رشته است برای فیلتر کردن داده های نمایش داده شده در هر صفحه
  • در خط شماره ۲۶  الی ۳۶ یک حلقه شرطی قرار دادیم که اگر جستجویی صورت نگرفته باشد ابتدا صفحه ی یک را نمایش بده در غیر اینصورت فیلترهای مربوط به جستجوی داده ها. و این موارد را توسط یک viewbag به ویو انتقال میدهیم که در خط ۳۴ مشخص کردیم.
  • در خط ۵۳ گفتیم در هر صفحه تنها ۳ رکورد نمایش بده و به اضای هر داده ی اضافه تری یک صفحه اضافه کن که در خط ۵۴ این کار را انجام دادیم
  • در نهایت در خط ۵۵ گفتیم لیستی از داده ها را نمایش بده به صورتیکه هم Pagesize وجود داشته باشد و هم pageNumber و توسط این دو return View کن
  • در ویو و در خطوط ۱ و ۲ ویژوال استودیو ما دو فضای نامی مربوط به پکیج را اضافه کردیم تا این صفحه این اکستنشن ها را شناخته و از آن ها استفاده کند و فضای نامی اصلی را کامنت کردیم.
  • یعنی در خط یک به طور خاص تعریف کردیم که آبجکت های مرتبط با PageList را برای نمایش آجکت های این صفحه استفاده کن
  • در خط ۲ گقتیم برای استفاده از خط یک نیاز است تا دسترسی به این MVC helper مربوط به این dll را داشته باشی
  • در خط ۱۵ View نیز گفتیم اطلاعات را از متد Get بخوان. به صورت پیش فرض BeingForm برای دریافت و نمایش اطلاعات از متد Post استفاده می کند که این به معنانی این است که پارامترها را توسط HTTP انتقال می دهد نه از طریق کوئری های URL . وقتی شما به طور مشخص از HTTP GET استفاده می کنید، اطلاعات فرم توسط رشته های اطلاعاتی URL منتقل می شوند. اما در استاندارد و راهنمای وب W3C (برای اطلاعات بیشتر به W3C guidelines for the use of HTTP GET مراجعه نمایید) پیشنهاد  می شود شما از GET زمانی استفاده نمایید که اکشن نتایجی را برای نمایش نشان نخواهد داد
  • در خط ۵۹ ویژوال استودیو ابتدا تمامی اطلاعات را شمرده و تعداد نمایش در هر صفحه را نیز از اکشن کنترلر میخواند (که در اینجا نمایش در هر صفحه ۳ می باشد) و در نهایت تعداد صفحات برای نمایش را محاسبه می کند و در خط ۶۰ نیز صفحات قبل و بعد را محاسبه و لینک دار می کند.
  • pageListPager در تهیه شمارش صفحات کمک می کند و به شما قدرت و انعطاف کاستومایز کردن را می دهد که شامل آدرس دهی ها و نحوه ی نمایش است. جهت اطلاعات بیشتر می توانید TroyGoode / PagedList را مشاهده نمایید.

 

در قسمت آخر آموزش Entity Framework 6 Code First – بخش سوم میخواهیم به بررسی آمار و ارقام بپردازیم! یعنی ببینیم در هر EnrollmentDate چه تعداد دانشجو ثبت نام کرده اند

ابتدا یک فولدر به نام ViewModels ایجاد و در آن یک کلاس با نام EnrollmentDateGroup ایجاد می کنیم و کدهای زیر را در آن قرار می دهیم

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace VaniaUniversity.ViewModels
{
    public class EnrollmentDateGroup
    {
        [DataType(DataType.Date)]
        public DateTime? EnrollmentDate { get; set; }
        public int StudentCount { get; set; }
    }
}

و سپس در کنترلر HomeController دو فضای نامی زیر را اضافه می نماییم

using VaniaUniversity.ViewModels;
using VaniaUniversity.DAL;

و سپس بعد از باز شدن کلاس ها ی این کنترلر دیتابیس را به آن معرفی خواهیم کرد توسط کد زیر

namespace VaniaUniversity.Controllers
{
    public class HomeController : Controller
    {
        private SchoolContext db = new SchoolContext();

و در نهایت در اکشن About کدهای زیر را جایگزین می نماییم

        public ActionResult About()
        {
            IQueryable<EnrollmentDateGroup> data = from student in db.Students
                                                   group student by student.EnrollmentDate into dataGroup
                                                   select new EnrollmentDateGroup()
                                                       {
                                                           EnrollmentDate = dataGroup.Key,
                                                           StudentCount = dataGroup.Count()
                                                       };

            return View(data.ToList());
        }

و در نهایت از متد Dispose استفاده خواهیم کرد

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

یعنی کدهای HomeController باید طبق کدهای زیر باشد

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VaniaUniversity.ViewModels;
using VaniaUniversity.DAL;

namespace VaniaUniversity.Controllers
{
    public class HomeController : Controller
    {
        private SchoolContext db = new SchoolContext();
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            IQueryable<EnrollmentDateGroup> data = from student in db.Students
                                                   group student by student.EnrollmentDate into dataGroup
                                                   select new EnrollmentDateGroup()
                                                       {
                                                           EnrollmentDate = dataGroup.Key,
                                                           StudentCount = dataGroup.Count()
                                                       };

            return View(data.ToList());
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

وحال نوبت تغییرات در View است . Views/Home/About.cshtml را باز می نماییم

@model IEnumerable<VaniaUniversity.ViewModels.EnrollmentDateGroup>
@{
    ViewBag.Title = "امار ثبت نامی دانشجویان";
}

<table>
    <tr>
        <th>
            تاریخ ثبت نام
        </th>
        <th>
            دانشجویان
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @item.StudentCount
            </td>
        </tr>
    }
</table>

و طبق معمول سیو و ریبیلد و اجرای پروژه . . .

۰۳۷

شکل شماره ۳۷-۳

به همین راحتی :)

[alerts title="سورس پروژه" type="info"]دانلود فایل سورس پروژه آموزش Entity Framework 6 Code First – بخش سوم با حجم ۳٫۵۰ مگابایت[/alerts]

/پایان آموزش Entity Framework 6 Code First – بخش سوم /

مشاهده ی بخش اول : آموزش Entity Framework 6 Code First

مشاهده بخش دوم : آموزش Entity Framework 6 Code First