Selected event not raised for ObjectDatasource whe

2019-09-16 12:57发布

I've a Gridview control using an ODS(ObjectDataSource) to fetch data. For the best performance and efficiency, I've turned-off the view state of Gridview (i.e. EnableViewstate = "false".

And I've also enabled caching in the associated Objectdatasource. This eliminates as much as 50-60% performance optimization because it eliminates the DB round-trip .. courtesy ODS Caching.

So, after this I got stuck into the famous "ODS sorting" issue but I managed to invent a tricky solution for it and its working fine:

Optimize Pagination & Sorting with ObjectDataSource having EnableCaching = true

Next pagination, it is also working fine. Now, I need to display "Total records: X" at the top of the Gridview. Well, I deployed the following method:

protected void ods_Selected(object sender, ObjectDataSourceStatusEventArgs e)
        {
            if(e.ReturnValue != null && e.ReturnValue.GetType() == typeof(int))
                base.setTotalLabel(lblTotal, e.ReturnValue);
        }

Don't confuse - base.setTotalLabel is my own method to set the label text with the count. This is also working fine but the issue is that -

Whenever, the ODS fetches data from its Cache it won't trigger the ODS_Selecting or ODS_Select events. They are simply "by-passed" because it takes data from cache. This is when I fail to refresh the Total records count!

I hope I've explained my problem good, this is tricky. I'm ready to do any trick or dirty coding for this because I want to maintain the ODS-caching and I can't rollback changes just because of a few incidental "mis-updates".

Pls help!

3条回答
欢心
2楼-- · 2019-09-16 13:52

I solved this by storing the record count in a session variable during the selected event:

protected void odsSearchResults_Selected(object sender, ObjectDataSourceStatusEventArgs e)
    {
        DataTable resultsTable = e.ReturnValue as DataTable;
        if (resultsTable == null)
        {
            return;
        }
        Session["ResultCount"] = resultsTable.Rows.Count;
        lblRecordCount.Text = resultsTable.Rows.Count.ToString();
    }

Then in Page_Load I display the record count if the session var is not null:

if(Session["ResultCount"] != null)
{
    lblRecordCount.Text = Session["ResultCount"].ToString();
}

Now lblRecordCount will show the record count if the data comes from the cache or not

查看更多
别忘想泡老子
3楼-- · 2019-09-16 13:56

This worked for me I set the CacheKeyDependency and I explicitly set it to a new value whenever I want to refresh. I pass &refresh=1 in querystring if I want to explicitly refresh.

In .aspx -

<asp:ObjectDataSource ID="odsOrg" runat="server" SelectMethod="SearchOrg" ... EnableCaching="true" CacheDuration="60" CacheKeyDependency="key1">

In code behind -

public const string argRefresh = "refresh=1";
public void CheckExpiredCacheKey(string ckey)
{
 if (Cache[ckey] == null) 
  Cache[ckey] = new object(); //Set Cache key which will b used to manually expire ODS cache     

if (!IsPostBack && Request.QueryString["refresh"] == "1")//check refresh flag
 {
    //Cache.Remove(ckey);//NOT NEEDED: use the following instead
    Cache[ckey] = new object();// Needed otherwise it'll call Grid-populate twice
 } 
}
查看更多
Anthone
4楼-- · 2019-09-16 13:57

I have the exact same problem?

A solution I have been doing is to call the select count method again (via BLL) in the gridview databinding method and storing this in a viewstate var then using it to display the number of records. But this leads to two things:

  • another call to the DB count sp (defeats caching purpose)
  • conflict of presentation i.e. number of cached records displayed may not match the actual number(which is up-to-date)
查看更多
登录 后发表回答