Можем ли мы использовать те же данные для pagemethod и webmethod в ASP.NET?

Я пытаюсь создать новую веб-страницу, где мне нужно отобразить почти 10 различных gridviews и диаграмм.

Gridviews привязаны к событию pageload, и диаграммы отображаются с использованием метода jquery-ajax (с использованием amcharts, а также с помощью высокоскоростных диаграмм), вызывая WebMethod.

Изначально я реализовал страницу таким образом, что после выполнения того же набора хранимых процедур для gridviews (для отображения данных в виде сетки) и webmethods (для рисования диаграмм). Такие же sps выполняются дважды для этой страницы (один для сетки и другой для диаграммы). Для сбора данных необходимо выполнить 10 sps.

Итак, для улучшения производительности страницы я создал статический datatable, как этот

static DataTable Report1;

и привязал gridview следующим образом.

private void gvbindReport1()
    {
        try
        {            
            Report1 = new DataTable();//refreshed datatable 
            DataSet ReportDS1 = objmvbl.GetReportGraph(ClientID, date_From, date_To);
            if (ReportDS1.Tables.Count > 0)
            {
                Report1 = ReportDS1.Tables[0];//bindinding data to static datatable

            }
            GdReport.DataSource = Report1;
            GdReport.DataBind();
        }
        catch (Exception ex)
        {
            Log.Errlog("Error Occured in  gvbindReport1 : " + ex.Message.ToString());
        }

    }

и внутри web-метода я использовал тот же тип данных, что и для рисования диаграммы как это

 [System.Web.Services.WebMethod]
    public static string GetDataReport1()
    {
        System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
        Dictionary<string, object> row;
        try
        {
            //processing for the data inside static datatable
            if (Report1.Rows.Count > 0)
            {
                foreach (DataRow dr in Report1.Rows)
                {
                    row = new Dictionary<string, object>();
                    foreach (DataColumn col in Report1.Columns)
                    {
                        row.Add(col.ColumnName, dr[col]);
                    }
                    rows.Add(row);
                }
            }
        }
        catch (Exception ex)
        {
            Log.Errlog("Error Occured in  GetDataReport WebMethod of Report Page : " + ex.Message.ToString());
        }

        return serializer.Serialize(rows);

    }

с этим я могу показать как сетку, так и диаграммы.

Теперь, пожалуйста, скажите мне, что это правильный подход к работе с веб-методами? Я прочитал, что веб-метод не имеет никакого отношения к странице и всем. Пожалуйста, скажите мне, какие недостатки этого метода.

Если это неверно, пожалуйста, предложите лучший способ улучшить производительность страницы.

Ответ 1

Нет, это не правильный метод. Поскольку вы объявили DataTable как static (статическая переменная имеет область приложения и не может быть создана), все

пользователи получат тот же результат (последние обновленные значения).

Вы можете реализовать это в параллельном тестировании.

Пожалуйста, проверьте следующий сценарий:

dtbl - это статическая dataTable которая инициализируется на домашней странице, и вы создаете еще один экземпляр datatable на странице индекса (оба загружаются, как показано ниже).

Главная

public static DataTable dtbl;
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        dtbl = new DataTable();
        dtbl.Columns.Add("id");
        dtbl.Columns.Add("name");
        for (int i = 0; i < 10; i++)
        {
            DataRow dr = dtbl.NewRow();
            dr["id"] = i.ToString();
            dr["name"] = i + 1;
            dtbl.Rows.Add(dr);
        }
    }
}

Индексная страница

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        home.dtbl = new DataTable();
    }
}

Теперь установите точку останова на каждой странице загрузки и запустите приложение,

  • Откройте обе страницы в separate tab.
  • Обновите домашнюю страницу и проверьте, отображаются ли столбцы
  • Теперь перейдите на следующую вкладку (индекс) и обновите ее (для dt создается новый экземпляр). Это повлияет на таблицу данных, теперь вы получите новую таблицу данных и дома.
  • Таким образом, если эти два процесса/страницы выполняются одновременно, последнее значение будет получено для обеих страниц. Вот почему я говорю, что это будет реализовано в тестировании параллелизма.

Вы можете использовать сеанс в этом случае. Рассмотрим следующий код:

Главная

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        dtbl = new DataTable();
        dtbl.Columns.Add("id");
        dtbl.Columns.Add("name");
        for (int i = 0; i < 10; i++)
        {
            DataRow dr = dtbl.NewRow();
            dr["id"] = i.ToString();
            dr["name"] = i + 1;
            dtbl.Rows.Add(dr);
        }
        if (((DataTable)Session["MyDatatable"]).Columns.Count < 0)
        {
            Session["MyDatatable"] = dtbl;
        }
        else
        {
            dtbl = (DataTable)Session["MyDatatable"];
        }
    }
}

Ответ 2

Прежде всего, не используйте в качестве основного правила статические переменные в веб-приложении. Они действуют как глобальные переменные и не создаются с каждым запросом.

Я бы также не предложил вам использовать DataTables до уровня вашего пользовательского интерфейса. Вместо этого работайте с сильно типизированными объектами.

  • Создайте модель объекта, который вы пытаетесь связать.

Как, например, если у вас есть таблица с именем человек, которая имеет следующие поля.

Id | first_name | last_name | audit_ts

Вы можете создать объект как таковой:

public class Person
{
    public int Id {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
}
  1. Теперь в отдельных функциях в каком-то классе вы можете вызвать свою хранимую процедуру из базы данных, а затем перевести строки таблицы в таблицу лиц в список объекта Person.

  2. Теперь вместо того, чтобы дважды вызывать вашу хранимую процедуру, чтобы получить одни и те же данные, что только снижает производительность вашего приложения, вы можете вместо этого привязать свое представление сетки к вашему коду в событии Page_Load. Просто привяжите таблицу HTML после того, как сделаете вызов своего веб-метода, который, я считаю, находится в code-behind. Вы можете ссылаться на этот пост относительно того, как связать вашу таблицу HTML с объектом JSON, возвращенным вашим Ajax.

  3. Таким образом, вы делаете один звонок на сервер и в базу данных, чтобы использовать те же данные для привязки вашей таблицы, а также к вашим диаграммам.

Ответ 3

Это хороший прецедент для малоиспользуемого объекта Cache Object. Многие пользователи понимают ViewState и SessionState, однако объект Cache не так широко используется, и хотя концепция очень похожа, более гибким.

Если ваша страница дважды вызывает 10 хранимых процедур (один раз для ваших гридов и второй раз для ваших диаграмм), то позволяет повысить производительность примерно на 100% за счет исключения дополнительных вызовов с помощью объекта Cache

У вас есть один вызов хранимых процедур в отдельном методе, который заполняет ваш кеш-объект данных, который затем повторно используется во всем приложении.

private void loadReport1IntoCache()
{
  //...load your data from DB into the Report1 variable here


  //this line is new, and it saves your data into a global Cache variable
  //with an absolute expiration of 10 minutes
  Cache.Insert("Report1", Report1, null,
  DateTime.Now.AddMinutes(10d), 
  System.Web.Caching.Cache.NoSlidingExpiration);


}

Затем, когда вы находитесь внутри других методов, вы можете использовать переменную Cache вместо повторного вызова хранимых процедур. Например:

[System.Web.Services.WebMethod]
public static string GetDataReport1()
{
   //first load the application variable before performing your other work
   DataTable myCachedReport1Data = (DataTable)Cache["Report1"];
   //did the Cache expire?
   if (myCachedReport1Data == null)
   {
   //if so refresh it
   loadReport1IntoCache();
   //and then assign the variable the contents of the refresh and proceed
   myCachedReport1Data = (DataTable)Cache["Report1"];
   }

   //other work here, utilizing the myCachedReport1Data variable
}

и для привязки сетки:

private void gvbindReport1()
{
    try
    {            
        DataTable myCachedReport1Data = (DataTable)Cache["Report1"];
        //did the Cache expire?
        if (myCachedReport1Data == null)
        {
          //if so refresh it
          loadReport1IntoCache();
          //and then assign the variable the contents of the refresh
          myCachedReport1Data = (DataTable)Cache["Report1"];
        }

        GdReport.DataSource = myCachedReport1Data ;
        GdReport.DataBind();
    }
    catch (Exception ex)
    {
        Log.Errlog("Error Occured in  gvbindReport1 : " +  ex.Message.ToString());
    }

}

Теперь вам нужно будет сделать несколько вещей, не упомянутых здесь. Вы должны учитывать, когда вы хотите, чтобы ваши данные кэша истекали (приведенный пример составляет 10 минут). Также вы должны подумать, хотите ли вы, чтобы это было абсолютное количество минут (абсолютное время истечения срока действия) или несколько минут после последнего доступа (раздвижной срок действия). В вашем случае, вероятно, абсолютное истечение срока действия, но только вы это знаете. Затем вы установите истечение, когда вы устанавливаете содержимое переменной.

Смотрите документацию Cache: https://msdn.microsoft.com/en-us/library/6hbbsfk6.aspx

Добавление данных кэша: https://msdn.microsoft.com/en-us/library/18c1wd61.aspx

Извлечение данных кэша: https://msdn.microsoft.com/en-us/library/xhy3h9f9.aspx

Ответ 4

Глядя на образец кода, который вы указали (и параметры date_from и date_to, которые вы переходите на GetReportGraph()) Я предполагаю:

  • у вас есть 2 поля ввода, где пользователь задает диапазон дат и затем передает данные (вызывая обратную передачу), на основе которых вы фильтруете записи и показываете как в сетке, так и в графике.

    /li >
  • поскольку разные пользователи будут предоставлять разные диапазоны дат, вы не хотите показывать одни и те же данные всем пользователям.

  • поскольку данные отфильтрованы, но не будут иметь тысячи записей.

Я не уверен, какие функции сетки вы используете. Используется ли это только для отображения табличных данных только для чтения? Если да, вы можете рассмотреть подход, данный @Nabin Karki Thapa. Если не проверить альтернативный подход ниже:

После того, как вы получили таблицу данных и привязали ее к виду сетки, немедленно сериализуйте ее в JSON и зарегистрируйте ее как блок script (определите переменную JS и назначьте сериализованный JSON в качестве значения).

На стороне клиента, а вместо того, чтобы ссылаться на web-метод, чтобы получить объект JSON, используйте переменную JS, которую вы зарегистрировали. Таким образом вы избежите вызова метода Web (AJAX) и вызова дополнительной хранимой процедуры вообще.