Lazy Loading درMVC

شنبه 9 اردیبهشت 1396

ما در این مقاله قصد داریم که به معرفی ، توضیح و پیاده سازی Lazy Loading بپردازیم و نکاتی را در این رابطه برای شما ارائه دهیم.Lazy Loading تکنیکیست که داده ها را بر اساس درخواست زمانیکه نیاز باشد بارگذاری میکند،که این باعث بهبود کارایی و عملکرد برنامه است.

 Lazy Loading درMVC

معرفی

 Lazy Loading تکنیکیست که داده ها را بر اساس درخواست زمانیکه نیاز باشد بارگذاری میکند.که این باعث بهبود کارایی و عملکرد برنامه است.اجازه دهید یک سناریو بسازیم،در جایی که ما مقدار زیادی رکورد داریم و میخواهیم آن ها را به کاربر نمایش بدهیم این روش راهی بسیار مناسب برای بالابردن بهره وری برنامه است.با این حال زمانیکه شما هزار از رکوردها را در یک زمان بارگذاری میکنید ، زمان بیشتری برای رندر نتایج میگیرد.اگر قرار باشد داده ها زمانیکه  بارگذاری میشوند به کاربر ارائه داده شوند.به منظور جلوگیری از برخورد با این مشکل ، ما نیاز داریم که از مفهوم صفحه بندی یا  Lazy Loading استفاده کنیم. زمانی که کاربر صفحه را به سمت پایین اسکرول میکند ،  Lazy Loading ، داده ها را قدم به قدم بارگذاری میکند .

مورد نیاز- ما 500 پرونده در DataSource داریم(فایل های متنی یا پایگاه داده).زمانیکه صفحه برای اولین بار بارگذاری میشود فقط 20 تا از رکورد ها را نمایش میدهد.زمانیکه کاربر به سمت پایین اسکرول کند ،این نتیجه بعدی را نمایش میدهد.

با استفاده از کد

برای توصیف از لحاظ فنی برای بالا باید ذکر کنیم که ما از فایل متنی که دارای 500 رکورد است به عنوان DataSource استفاده میکنیم.اکشن کنترلر20 تا از رکورد ها را برای اولین بار بارگذاری میکند.زمانی که کاربر به سمت پایین اسکرول میکند ، این به سرور درخواستی از نوع Ajax برای بارگذاری بقیه رکورد ها میدهد.قطعه کدی از جاوا اسکریپت با استفاده از چک کردن ارتفاع صفحه و طول اسکرول زمانی که کاربر به سمت پایین اسکرول کند چک میکند.عکس زیر ساختار پروژه است.قدم زیر را دنبال کنید.

شکل 1) نمودار پروژه Lazy Loading

مدل

اجازه دهید به طراحی موجودیت پروژه بپردازیم.ویژگی هایی مانند: ID ، Name ، ManagerName و Email را شامل میشود.

public class Project  
{  
    public string ID { get; set; }  
    public string Name { get; set; }  
    public string ManagerName { get; set; }  
    public string Email { get; set; }  
}  

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

public List<Project> GetProjectList()  
{  
    string projectFile = HostingEnvironment.MapPath("~/App_Data/Projects.txt");  
    List<Project> tempList = new List<Project>();  
  
    foreach (string line in File.ReadAllLines(projectFile))  
    {  
        var parts = line.Split('|');  
        tempList.Add(new Project()  
        {  
            ID = parts[0],  
            Name = parts[1],  
            ManagerName= parts[2],  
            Email = parts[3]  
        });  
    }  
  
    return tempList;  
}  

کنترلر

کنترلرشامل اکشن های زیر است.

Index()

زمانی که کنترلر Home را فراخوانی میکنیم این اکشن پیشفرض است و این اکشن به اکشن ()GetProject   ما را هدایت میکند.

GetProjects()

این تابع چک میکند که آیا درخواست امده  از نوع AJAX است.اگر بله ، این اکشن داده ها را به وسیله  partialview ارسال میکند ، در غیر این صورت با viewbag داده ها را ارسال خواهد کرد.

GetRecordsForPage()

این اکشن شماره صفحه را به صورت یک پارامتر دریافت میکند و اینکه این اکشن برای دریافت داده های مورد نیاز از DataSource از LINQ استفاد میکند.

public const int RecordsPerPage = 20;  
public List<Project> ProjectData;  
  
public HomeController()  
{  
    ViewBag.RecordsPerPage = RecordsPerPage;              
}  
  
public ActionResult Index()  
{  
    return RedirectToAction("GetProjects");  
}          
  
public ActionResult GetProjects(int? pageNum)  
{  
    pageNum = pageNum ?? 0;  
    ViewBag.IsEndOfRecords = false;  
    if (Request.IsAjaxRequest())  
    {  
        var projects = GetRecordsForPage(pageNum.Value);  
        ViewBag.IsEndOfRecords = (projects.Any());  
        return PartialView("_ProjectData", projects);  
    }  
    else  
    {  
        var projectRep = new ProjectRepository();  
        ProjectData = projectRep.GetProjectList();  
  
        ViewBag.TotalNumberProjects = ProjectData.Count;  
        ViewBag.Projects = GetRecordsForPage(pageNum.Value);  
  
        return View("Index");  
    }  
}  
  
public List<Project> GetRecordsForPage(int pageNum)  
{  
    var projectRep = new ProjectRepository();  
    ProjectData = projectRep.GetProjectList();  
  
    int from = (pageNum * RecordsPerPage);  
  
    var tempList = (from rec in ProjectData  
                    select rec).Skip(from).Take(20).ToList<Project>();  
  
    return tempList;  
}  

Viewها

برای تعریف ماژول view ها ما  _Layout.cshtm و Index() و _Projectdata.cshtml را تعریف میکنیم.

_Layout.cshtml

این همان MasterPage است که با نام Layout در اینجا استفاده میشود.در بخش  Header تمام فایل های Js و Css تزریق شده اند.در قسمت Body کد RenderBody() وجود دارد که محتویات صفحه ای که از آن ارث بری کرده است در داخل آن ترجمه (Render) میشود.این صفحه در صفحه _ViewStart.cshtml رفرنس داده میشود.

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8" />  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>@ViewBag.Title</title>  
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>  
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>  
    <script src="~/Scripts/bootstrap.min.js"></script>  
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />  
    <link href="~/Content/Site.css" rel="stylesheet" />  
</head>  
<body>  
    <div class="container body-content">  
        @RenderBody()  
  
        <hr />  
  
        <div id="loading">  
            <img src='~/Content/spin.gif' /><p style="color: red;"><b>Loading Next...</b></p>  
        </div>  
  
        <footer>  
            <p>Copyright© @DateTime.Now.Year </p>  
        </footer>  
    </div>  
    @RenderSection("scripts", required: false)  
</body>  
</html>  

Index.cshtml

این صفحه  به عنوان فرزند Layout است و آن بوسیله آدرس Views/Home/Index.cshtml صدا زده میشود و در آن کد های HTML برای نمایش رکورد ها موجود است و فایل های جاوا اسکریپت مورد نیاز به آن تزریق میشود.

@using LazyLoadInMVC.Models  
@{  
    ViewBag.Title = "LazyLoading Demo";  
}  
<div class="jumbotron">  
    <h1>LazyLoading Demo</h1>  
    <p class="lead">  
        This page is demo how to load records on demand.  
        Instead of loading all <span class="text-primary">@ViewBag.TotalNumberProjects</span> records,   
        let's load based on user requirement.  
  
        Scroll down the page then you will see that records are added to page.  
        It loads @ViewBag.RecordsPerPage records at a time and total no of records is <span class="text-primary">@ViewBag.TotalNumberProjects</span>.  
    </p>  
</div>  
  
<table class="table table-striped table-bordered table-condensed infinite-scroll">  
        <thead>  
            <tr>  
                <th>ID #</th>  
                <th>Name</th>  
                <th>Manager>  
                <th>Manager Email</th>  
            </tr>  
        </thead>  
        <tbody>  
            @Html.Partial("_ProjectData", (ViewBag.Projects as List<Project>))  
        </tbody>  
    </table>  
  
@section scripts{  
    <script src="~/Scripts/lazyLoading.js"></script>  
    <script type="text/javascript">  
        $(function () {  
            $("div#loading").hide();  
        });  
  
        var url = '@Url.RouteUrl("ProjectDataList")';  
        $(window).scroll(scrollHandler);  
    </script>  
}  

در کد قبلی، Url.RouteUrl() را تعریف کردیم که در پوشه RouteConfig.cs تعریف شده بود.در اینجا کد های زیر آورده شده است.

public static void RegisterRoutes(RouteCollection routes)  
{  
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  
    routes.MapRoute("ProjectDataList", "", new { controller = "Home", action = "GetProjects" });  
  
    routes.MapRoute(  
        name: "Default",  
        url: "{controller}/{action}/{id}",  
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }  
    );  
}  

_ProjectData.cshtml

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

این زمانی استفاده میشود که که درخواستی از نوع Ajax به سمت سرور برای دریافت داده ها با فرمت  HTML ارسال کنیم.

@model List<LazyLoadInMVC.Models.Project>  
  
@foreach (var cust in Model)  
{  
    <tr>  
        <td>@cust.ID</td>  
        <td>@cust.Name</td>  
        <td>@cust.ManagerName</td>  
        <td>@cust.Email</td>  
    </tr>  
}  

جاوا اسکریپت

حال زمان تعریف جاوا اسکریپت است، که  Lazy Loading را انجام میدهد.در قطعه کد زیر تابعی به اسم ()scrollHandler است، که زمانیکه هرگونه رویداد scroll در مرورگر رخ بدهد  صدا زده میشود.این تابع چک میشود اگر تفاوت مقادیر ارتفاع document و ارتفاع صفحه بزرگ تر از مقدار ()scrollTop مربوط به document باشد.اگر مقدارش  true بود ، یک درخواست Ajax به منظور افزایش عدد صفحه به سمت سرور ارسال میکند.در صورت موفقیت امیز بودن Ajax داده ها به جدول اضافه میشوند.

var page = 0,  
    inCallback = false,  
    isReachedScrollEnd = false;  
  
var scrollHandler = function () {  
    if (isReachedScrollEnd == false &&  
        ($(document).scrollTop() <= $(document).height() - $(window).height()))  
    {  
        loadProjectData(url);  
    }  
}  
  
function loadProjectData(loadMoreRowsUrl) {  
    if (page > -1 && !inCallback) {  
        inCallback = true;  
        page++;  
        $("div#loading").show();  
  
        $.ajax({  
            type: 'GET',  
            url: loadMoreRowsUrl,  
            data: "pageNum=" + page,  
            success: function (data, textstatus) {  
                if (data != '') {  
                    $("table.infinite-scroll > tbody").append(data);  
                    $("table.infinite-scroll > tbody > tr:even").addClass("alt-row-class");  
                    $("table.infinite-scroll > tbody > tr:odd").removeClass("alt-row-class");  
                }  
                else {  
                    page = -1;  
                }  
  
                inCallback = false;  
                $("div#loading").hide();   
            },  
            error: function (XMLHttpRequest, textStatus, errorThrown) {  
                alert(errorThrown);  
            }  
        });  
    }  
}  

Output

زمانیکه ما تغییرات را انجام میدهیم به برنامه اجازه Browse میدهیم.به صورت پیشفرض 20 تا رکورد را بارگذاری میکند و زمانیکه شما اسکرول کنید 20 تای بعدی را با ایکن Loading بارگذاری میکند.در شکل1 Id اخرین پروژه 1019 است.در شکل2 ،1039 است.بنابراین شما میتوانید بدانید که وقتی صفحه را به سمت پایین اسکرول کنید داده های بعدی بارگذاری میشوند.

شکل2)بارگذاری داده ها برای بار اول

شکل3)بارگذاری داده ها برای دومین بار

نتیجه

ما در اینجا در رابطه  Lazy Loading و پیاده سازی آن توضیح دادیم. Lazy Loading نوعی الگو برای پاسخ به تقاضاها است.

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

آموزش asp.net mvc

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

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

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید