0

I have a project which using DataTables. Its working as ajax request. Its completing in 8-12 seconds. I need to optimize this code but i don't know how. String Process is worst part.

    public JsonResult PageModel(Models.DataTable.ParamModel model, byte type)
    {
        DateTime startTime = DateTime.Now;
        using (var db = Helper.Context())
        {
            var allEntries = db.MembershipVacations.Where(i => i.Type == type).ToList();
            IEnumerable<DatabaseProcedure.Models.MembershipVacation> list = new List<DatabaseProcedure.Models.MembershipVacation>();

            Func<DbModels.MembershipVacation, string> orderingFunction = (c =>
                                                    model.iSortCol_0 == 0 ? c.Membership.Username : "");

            Func<DbModels.MembershipVacation, DateTime> dateOrderingFunction = (c =>
                                                    model.iSortCol_0 == 1 ? c.PostDate : 
                                                    model.iSortCol_0 == 3 ? c.StartDate :
                                                    model.iSortCol_0 == 4 ? c.EndDate : DateTime.MaxValue);

            /*Func<DbModels.MembershipVacation, string> orderingFunction = (c => model.iSortCol_0 == 1 ? c.ID.ToString() :
                                                    model.iSortCol_0 == 2 ? c.Membership.Username :
                                                    c.Description);*/

            if (User.IsInRole("Admin"))
            {
                if (model.sSearch.IsNull())
                {
                    if (model.sSortDir_0 == "asc")
                    {
                        list = allEntries
                            .OrderBy(orderingFunction);

                        if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
                        {
                            list = allEntries.OrderBy(dateOrderingFunction);
                        }
                    }
                    else
                    {
                        list = allEntries
                            .OrderByDescending(orderingFunction);


                        if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
                        {
                            list = allEntries.OrderByDescending(dateOrderingFunction);
                        }
                    }
                    list = list
                        .Skip(model.iDisplayStart)
                        .Take(model.iDisplayLength);
                }
                else
                {
                    list = allEntries
                        .Where(i =>
                        i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
                        || i.Membership != null && i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
                        || i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
                        || i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase));

                    if (model.sSortDir_0 == "asc")
                    {
                        list = list
                            .OrderBy(orderingFunction);

                        if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
                        {
                            list = list.OrderBy(dateOrderingFunction);
                        }

                    }
                    else
                    {
                        list = list
                            .OrderByDescending(orderingFunction);

                        if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
                        {
                            list = list.OrderByDescending(dateOrderingFunction);
                        }

                    }
                }
            }
            else
            {
                var approveList = db.MembershipVacationApproves.ToList();
                if (model.sSearch.IsNull())
                {
                    list = approveList
                        .Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
                        .Select(i => i.MembershipVacation)
                        .Distinct()
                        .Where(i => i.Type == type)
                        .Skip(model.iDisplayStart)
                        .Take(model.iDisplayLength);
                }
                else
                {
                    list = approveList
                        .Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
                        .Select(i => i.MembershipVacation)
                        .Distinct()
                        .Where(i =>
                        i.Type == type && (
                        i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
                        || i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
                        || i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
                        || i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)))
                        .Skip(model.iDisplayStart)
                        .Take(model.iDisplayLength);
                }
            }


            List<string[]> result = new List<string[]>();
            foreach (var item in list)
            {
                var waiting = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Waiting) > 0;
                var cancel = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Cancel) > 0;
                var approve = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Approve) == item.MembershipVacationApproves.Count;
                var edit = item.Membership.MembershipRelation != null ? item.Membership.MembershipRelation.OwnerID == UI.Helper.User.ID : false;
                var canApprove = item.MembershipVacationApproves.Count(i => i.MembershipID == UI.Helper.User.ID) == 1;


                StringBuilder name_link = new StringBuilder(),
                    durumu = new StringBuilder(),
                    islemler = new StringBuilder();

                if (item.Membership.Staff != null)
                {
                    name_link.Append("<a href=" + this.Url.Action("Profile", "Staff", new { id = item.MembershipID }) + ">" + item.Membership.Username + "</a>");
                }
                else
                {
                    name_link.Append(item.Membership.Username);
                }
                if (!cancel)
                {
                    if (approve)
                    {
                        if (DateTime.Now < item.StartDate)
                        {
                            durumu.Append("<small class='btn green-bg'>İstek onayladı.</small>");
                        }
                        else
                        {
                            if (DateTime.Now > item.EndDate)
                            {
                                durumu.Append("<small class='btn green'>Kişi izinden dönmüş.</small>");
                            }
                            else
                            {
                                durumu.Append("<small class='btn green'>Kişi izinde.</small>");
                            }
                        }
                    }
                    else
                    {
                        durumu.Append("<small class='btn orange'>İstek onaylanması için bekleniyor.</small>");
                    }
                }
                else
                {
                    durumu.Append("<small class='btn red'>İstek iptal edilmiş</small>");
                }

                islemler.Append("<div class='btn-group'>");
                islemler.Append("<a class='btn green' href='#' data-toggle='dropdown'><i class='icon-user'></i>İşlemler");
                islemler.Append("<i class='icon-angle-down'></i></a>");
                islemler.Append("<ul class='dropdown-menu'>");

                islemler.Append("<li><a href='" + this.Url.Action("RequestDetail", "Vacation", new { id = item.ID }) + "' data-toggle='modal' data-target='#'><i class='icon-search'>");
                islemler.Append("</i>İncele</a></li>");

                /*if (User.IsInRole("İzin Onaylama") || edit)
                {
                    islemler += "<li><a href='" + this.Url.Action("Request", "Vacation", new { id = item.ID }) + "'><i class='icon-search'>";
                    islemler += "</i>Düzenle</a></li>";
                }*/
                if (!(DateTime.Now > item.StartDate && approve) && canApprove)
                {
                    islemler.Append("<li><a href=" + this.Url.Action("ApproveRequest", "Vacation", new { id = item.ID }) + "><i class='icon-ok'></i>Onayla</a></li>");
                    islemler.Append("<li><a href=" + this.Url.Action("DeclinePage", "Vacation", new { id = item.ID }) + " data-toggle='modal' data-target='#'><i class='icon-remove'></i>Onaylama</a></li>");
                }

                islemler.Append("</ul>");
                islemler.Append("</div>");

                result.Add(
                    new string[] 
                    {
                        name_link.ToString(),
                        item.PostDate.ToString(),
                        item.Membership.Department != null ? item.Membership.Department.Name : string.Empty,
                        item.StartDate.ToString(),
                        item.EndDate.ToString(),
                        durumu.ToString(),
                        islemler.ToString()
                    });
            }

            var total = (DateTime.Now - startTime);

            System.Diagnostics.Debug.WriteLine("total ms "  + total.TotalMilliseconds);

            return Json(new
            {
                sEcho = model.sEcho,
                iTotalRecords = allEntries.Count(),
                iTotalDisplayRecords = allEntries.Count(),
                aaData = result
            }, JsonRequestBehavior.AllowGet);

        }

    }

Worst part is last foreach process for make buttons and permissions

1 Answer 1

1

I would guess that you have an N+1 SQL query issue in your last foreach loop: you build list then trigger 5 SQL queries for each item in the list.

Advice to diagnose and fix:

  • Install MiniProfiler and enable database profiling - then you'll be able to see which SQL queries are being triggered by the request, and if you have any duplicate queries.
  • Make use of EntityFramework's Include method, to eager load related data when you're querying the items for list. This will save EF from having to issue separate duplicate queries within your foreach.
1
  • I fixed it. I was doing wrong code for at var canApprove = item.MembershipVacationApproves.Count(i => i.MembershipID == UI.Helper.User.ID) == 1; UI.Helper.User was doing alot of process for nothing everytime. THANKS !
    – alim
    Commented Jul 30, 2013 at 8:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.