Athul Athul - 17 days ago 6
ASP.NET (C#) Question

Difference between Using same datatable for pagemethod and webmethod

I am trying to create a new webpage where i need to display almost 10 different gridviews and charts for each grid data.

Gridviews are binded on pageload event and charts are displayed using jquery-ajax method (using amcharts as well as highcharts) by calling WebMethod.

Initially i implemented the page in a way that after executing stored procedure gridview binded and inside webmethod also executing the same sp for drawing chart.So same sp is executed twice for this page(one for grid and another for chart).10 sps needs to execute for grid and same 10 for charts.

So for improving the page performance i have created static datatable like this

static DataTable Report1;


and binded the gridview like this.

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());
}

}


and inside the webmethod i have used the same datatable for drawing the chart
like this

[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);

}


with this i am able to show both grid and charts.

Now Please tell that, is this a correct approach to deal with webmethods? i have read that webmethod have no relation to the page and all.Please Tell me the draw backs of this method.

If this is wrong way,Please give some idea to improve the page performance?

Answer

No, this is not the correct method. Since you have declared the DataTable as static (a static variable has application scope and cannot be instantiated) all

users will get the same result (last updated values).

You can realize this in concurrency testing.

Please check the following scenario:

Consider dtbl is the static dataTable which is initialized on the home page, and you create another instance instance of `datatable on the index page (both are in page load as given below).

Home

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);
        }
    }
}

Index page

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

Now put a breakpoint in each page load and run the application,

  • Open both the pages in separate tab.
  • Refresh the home page and check whether the columns are showing
  • Now go to next tab (index) and refresh it (a new instance is created for dt). It will affect the datatable now you will get the new datatable in home also.
  • So if these two processes/pages are concurrently executed the latest value will get for both the pages. That's why I am saying it will realize this in concurrency testing.

You can make use of a session in this case. Consider the following code:

Home

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"];
        }
    }
}
Comments