Adding/Editing products gets Reeaaaally slow when adding lots of categories

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
14 年 前
When we add a high number of categories/subcategories in our nopCommerce store (>250) adding and editing of products gets really slow.

Managing products hardly responds. Frontend performance seems to be ok.
14 年 前
by default, hte categories tree in the admin section loads the products as well under each category.

what you can do is remove the code that loads the products into the tree and you'll have a much faster interfcae.

that's what i did and it works better.
14 年 前
sch09 wrote:
by default, hte categories tree in the admin section loads the products as well under each category.

what you can do is remove the code that loads the products into the tree and you'll have a much faster interfcae.

that's what i did and it works better.

Or just set 'Display.HideProductsOnCategoriesHomePage' setting to 'true'
14 年 前
I think there is some miscommunication.

The problem is not in the category tree. The tree itself works well. (Actually there are only few products on the site yet, because they are being entered)


The problem is in adding or editing Products itself.

When we try to save a product the admin interface almost stalls. This only occurs when a high number of categories has been created.
14 年 前
I see. I'll create a work item for this issue
14 年 前
yes that is true. loading the product or the variant details is a bit slow .

maybe we should think o using lazy loading to minimize the load .
13 年 前
Hi, just to give an update on this issue.

At first I assumed the problem to be the nested loop while loading the product categories. However this assumption appeared to be wrong. I have finally isolated the problem to be caused by the categorymapping datagrid bind method. Because it loads to many categories the loading gets unacceptably slow.

Implementing paging in this gridView seems to solve the issue.

I have modified the gridView declaration in productCategories.ascx as followed:

<asp:GridView ID="gvCategoryMappings" runat="server" AutoGenerateColumns="false"
    Width="100%" OnPageIndexChanging="gvCategoryMappings_PageIndexChanging" AllowPaging="true" PageSize="15">

In the CodeBehind I have added 3 methods:

        /// <summary>
        /// Remembers the values that have been checked in the gridview during paging
        /// The checked values will be temporarily stored in the users session
        /// </summary>
        private void RememberOldValues()
        {
            ArrayList categoryIDList = new ArrayList();
            foreach (GridViewRow row in gvCategoryMappings.Rows)
            {
                CheckBox cbCategoryInfo = row.FindControl("cbCategoryInfo") as CheckBox;
                HiddenField hfCategoryID = row.FindControl("hfCategoryID") as HiddenField;
                int categoryID = int.Parse(hfCategoryID.Value);
                bool result = cbCategoryInfo.Checked;
            
                // Check in the Session
                if (Session["CHECKED_ITEMS"] != null)
                {
                    categoryIDList = (ArrayList)Session["CHECKED_ITEMS"];
                }

                if (result == true)
                {
                    if (!categoryIDList.Contains(categoryID))
                    {
                        categoryIDList.Add(categoryID);
                    }
                }
                else
                {
                    categoryIDList.Remove(categoryID);
                }
            }
            if (categoryIDList != null && categoryIDList.Count > 0)
            {
                Session["CHECKED_ITEMS"] = categoryIDList;
            }
        }

        /// <summary>
        /// Restores the checked values in the gridview that have been previously selected on the current page
        /// (But have not been saved yet)
        /// </summary>
        private void RePopulateValues()
        {
            ArrayList categoryIDList = (ArrayList)Session["CHECKED_ITEMS"];
            if (categoryIDList != null && categoryIDList.Count > 0)
            {
                foreach (GridViewRow row in gvCategoryMappings.Rows)
                {
                    HiddenField hfCategoryID = row.FindControl("hfCategoryID") as HiddenField;
                    int categoryID = int.Parse(hfCategoryID.Value);

                    if (categoryIDList.Contains(categoryID))
                    {
                        CheckBox cbCategoryInfo = row.FindControl("cbCategoryInfo") as CheckBox;
                        cbCategoryInfo.Checked = true;
                    }
                }
            }
        }

        protected void gvCategoryMappings_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            RememberOldValues();
            this.gvCategoryMappings.PageIndex = e.NewPageIndex;
            this.BindData();
            RePopulateValues();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                this.BindData();
            }
        }

The RememberOldValues and RepopulateValues are required to retain the checked entries during paging.
However when clicking the save button, at this moment the checked values on pages, other then the currently selected page, get lost.
I am trying to solve this issue. (Probably this requires loading the checked entries from the session in the save method)

I will update you when the issue has been resolved.
It is likely that the same code will have to be implemented in the product variants and related products pages as this will give the same issue when a high number of items exist.

Regards,
Dennis Evers
Coders4you
13 年 前
I have been able to fix the problem by implementing paging in the category mapping gridview.

I had to modify several methods in the productcategory.ascx codebehind file for this to be working.
Is there any way I can submit this code so that you guys can review it and, if necessary, include it in the next release?
13 年 前
Hello coders4you! Could you share your code?

I have the same problem - slow work of product details page in admin area.
I have about 80 manufactures, 100 categories, 1 image (~60kb) and my overall page size is about 3Mb! The page itself - 1.9Mb.
I think this problem is not only about categories...
13 年 前
I appreciate what you have created.  It inspired me to implement it.  I was accomplishing the same thing with javascript but I had to turn off page validation to accomplish it.  I store values in a Dictionary list with key values and text values of the checkbox and when I save the collection I can loop through the new Dictionary.  The project I am working on is a Content Management System for a college and I was stumped on how to handle GridViews with paging.  Here is the code that I developed for a grid view for Departments that accomplishes everything you did:

    public Dictionary<int, string> Departments
    {
        get
        {
            if (ViewState["departments"] != null)
                return (Dictionary<int, string>)ViewState["departments"];
            else
                return new Dictionary<int, string>();
        }
        set { ViewState["departments"] = value; }
    }

    protected void gvDepartments_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DataRowView drv = (DataRowView)e.Row.DataItem;
            CheckBox cb = (CheckBox)e.Row.FindControl("cbDepartment");
            cb.InputAttributes.Add("value", drv["department_id"].ToString());
            foreach (KeyValuePair<int, string> item in Departments)
            {
                if ((int)drv["department_id"] == item.Key)
                    cb.Checked = true;
            }
        }
    }

    protected void DepartmentsPageChanging(object sender, GridViewPageEventArgs e)
    {
        RetainID();
        sds.ConnectionString = connString;
        sds.SelectCommand = DepartmentManager.GetSelectCommandForGrid();
    }

    protected void gvDepartments_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DataRowView drv = (DataRowView)e.Row.DataItem;
            CheckBox cb = (CheckBox)e.Row.FindControl("cbDepartment");
            cb.InputAttributes.Add("value", drv["department_id"].ToString());
            foreach (KeyValuePair<int, string> item in Departments)
            {
                if ((int)drv["department_id"] == item.Key)
                    cb.Checked = true;
            }
        }
    }

    private void RetainID()
    {
        foreach (GridViewRow row in gvDepartments.Rows)
        {
            CheckBox cb = (CheckBox)row.FindControl("cbDepartment");
            if (Departments.ContainsKey(int.Parse(cb.InputAttributes["value"])))
            {
                if (!cb.Checked)
                    Departments.Remove(int.Parse(cb.InputAttributes["value"]));
            }

            if (cb.Checked && !Departments.ContainsKey(int.Parse(cb.InputAttributes["value"])))
                Departments.Add(int.Parse(cb.InputAttributes["value"]), cb.Text);
        }
    }
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.