Saturday, March 24, 2012

Conditional Updating

Hi,

I have a GridView in a an UpdatePanel (set to conditional) which is triggered to update by a trigger every 5000ms. Right now, everytime the timer ticks, I get data out of the SQL server and bind it to the grid which is then redrawn on the client. However, what I'd like to do is .. put the DataSet from the SQL in a Session variable and always compare that one to the one retrieved from the SQL and redraw the grid ONLY when there was a change between those two DataSets.

The problem I'm having now is that I don't know if there is a way to leave the grid as is when the timer triggers. Since I have over a 100 rows in the grid, redrawing everything every 5000ms really causes CPU spikes in IE.

Anyone knows how to do that?

Thanks

Imagine 100s of clients hit your page, your server will smoke + all the clients' PC ........ =)

"The problem I'm having now is that I don't know if there is a way to leave the grid as is when the timer triggers. "

Don't set the <Triggers> to the Timer. Let the timer call a function and within the function you compare your data. If match then don't do a DataBind, if not match then do gridviewIDname.databind. However, storing a DataSet of 100+ rows into session variable is not a great way to do it. Plus you have to pull out another DataSet from the SQL to compare. That hurts your CPU + DB (every 5seconds). If you pull out one single value from the DB, that's much better.

hmmm I would do this way, but other people might have a better idea than I am.

idea:
Initially set Session("DataChanged") = false;
if the data from the DB is changed by someone, set Session("DataChanged") = true ...

In your function, which is called by your timer, check to see if Session("DataChanged") = true or not; if true then retrieve the data from the DB and bind it to your gridview (don't forget to set it back to false), else don't do anything. =)

Note: Doing this way will create another problem, how do you know if all of your clients has the updated data? LOL =)


Hello,

Maybe another direction.

You can experiment with a cached gridview inside the updatepanel.

The cache in Asp.net 2.0 also has a polling mechanism for changed data.
So you can use the trigger, and as long the data is not changed, the gridview use the cached data.

To use the polling, its necesary that you use SQL server and some changes in your web.config.

<system.web>

<cache>

<sqlCacheDependencyenabled="true"pollTime="1000">

<databases>

<addname="Northwind"

connectionStringName="Northwind"

pollTime="1000"/>

</databases>

</sqlCacheDependency>

</cache>

</system.web>

I never used this, because i have always made gridviews that are to mutch user depended. So caching was nothing for me.
But maybe you can do something with it in your case.

Marchu


Have you tried that both solutions?

It yes post it plz...which one is suited to use in terms of performance


Hi WishStar,

thanks for your concerns but in this particular scenario only 5 users are using this system thus storing this in a session variable shouldn't be a problem. You mentioned I shouldn't use Triggers in the UpdatePanel but how can I update the grid on a timer tick without doing a full postback?

I've thought of other solutions as well but as you noticed then you're facing other hurdles and as this is really only used by a couple people I think working with session variables should work fine. I can't use the ASP.NET/SQL caching mechanisms as not all the data I'm getting is coming out of SQL ;)


Regards,

Daikoku

WishStar99:

Imagine 100s of clients hit your page, your server will smoke + all the clients' PC ........ =)

"The problem I'm having now is that I don't know if there is a way to leave the grid as is when the timer triggers. "

Don't set the <Triggers> to the Timer. Let the timer call a function and within the function you compare your data. If match then don't do a DataBind, if not match then do gridviewIDname.databind. However, storing a DataSet of 100+ rows into session variable is not a great way to do it. Plus you have to pull out another DataSet from the SQL to compare. That hurts your CPU + DB (every 5seconds). If you pull out one single value from the DB, that's much better.

hmmm I would do this way, but other people might have a better idea than I am.

idea:
Initially set Session("DataChanged") = false;
if the data from the DB is changed by someone, set Session("DataChanged") = true ...

In your function, which is called by your timer, check to see if Session("DataChanged") = true or not; if true then retrieve the data from the DB and bind it to your gridview (don't forget to set it back to false), else don't do anything. =)

Note: Doing this way will create another problem, how do you know if all of your clients has the updated data? LOL =)


@.WishStar

Probably you're assuming that the timer is within an UpdatePanel? However, this doesn't work as there is a bug in ASP.NET AJAX when several timers are used on one page. They're resetting each other when they reside within UpdatePanels... that's why I have to user triggers right now.


Hello,

No, I did not assume that the timer is inside the UpdatePanel; because you said that you are using a Trigger in your initial post. I thought that there are more people using the page that you are working on; and if so, then it will be too heavy for the database to handle every 3 or 5 second to requiry. Since it's only 5 people, you can use what you are implementing right now.

Hold on, let me try a sample and see if i can figure out the way i mentioned above to you. Sorry for confusing you. Peace =)



After reviewing the session state and from my knowledge, i don't think session variable can be shared among users; if it does, then there will be a huge security hole. The only way that I can think of is a value (datetimestamp) save in the database. Instead of retrieving 100+ rows from the database for comparision, you can retrieve one value and compare it with the original value; if they are different then update the gridview if not then don't do anything.

However, if your way of doing it doesn't affect any performance, just leave the way it is. If it does down the road, then you might want to reconsider. Good Luck.


I think if we user Server Farm then, Session variable can be shared......

am i right ?


Hi,

my problem is not really performance or the session state (session states can not be shared amongst users but amongst applications - not perfectly sure about grid/farm scenarios though) but how to update the Grid only when needed. The problem is that when I remove the trigger and bind the grid in the ticker event, the whole page posts back and doesn't do an async postback in the UpdatePanel. Any idea how to solve that?

Thanks


hello,

can you post your HTML here and code behind? Thanks.


Hm, that'd be a bit much to post as I'm working with tabs and multi pages.

I'm just trying to find out how to do this in general:

I have a Grid within an UpdatePanel, basically something like this:

 <asp:UpdatePanel ID="UpdatePanel4" runat="server" UpdateMode="Conditional" EnableViewState="true"> <ContentTemplate> <radG:RadGrid ID="gridOrders" runat="server" AllowSorting="True" AllowFilteringByColumn="false" EnableAJAX="True" GridLines="None" Skin="QuikFills" OnItemDataBound="gridOrders_ItemDataBound" EnableViewState="true"> <MasterTableView AutoGenerateColumns="False" DataKeyNames="ClOrdID"> <Columns> <radG:GridBoundColumn DataField="ClOrdID" HeaderText="ID" ReadOnly="True" SortExpression="ClOrdID" UniqueName="ClOrdID" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="NewsReleaseID" HeaderText="NewsReleaseID" ReadOnly="True" SortExpression="NewsReleaseID" UniqueName="NewsReleaseID" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="Instrument.Symbol" HeaderText="Symbol" SortExpression="Instrument.Symbol" UniqueName="Symbol" AllowFiltering="true"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="Side" HeaderText="Side" SortExpression="Side" UniqueName="Side"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="OrderQty" DataType="System.Int32" HeaderText="OrderQty" SortExpression="OrderQty" UniqueName="OrderQty" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="Price" DataType="System.Decimal" HeaderText="Price" SortExpression="Price" UniqueName="Price" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="StopPx" DataType="System.Decimal" HeaderText="StopPx" SortExpression="StopPx" UniqueName="StopPx" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="AvgPx" DataType="System.Decimal" HeaderText="AvgPx" SortExpression="AvgPx" UniqueName="AvgPx" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="OrdType" HeaderText="OrdType" SortExpression="OrdType" UniqueName="OrdType" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="TimeInForce" HeaderText="TIF" SortExpression="TimeInForce" UniqueName="TimeInForce" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="OrdStatus" HeaderText="OrdStatus" SortExpression="OrdStatus" UniqueName="OrdStatus"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="FilledQty" DataType="System.Int32" HeaderText="FilledQty" SortExpression="FilledQty" UniqueName="FilledQty" AllowFiltering="false"> </radG:GridBoundColumn> <radG:GridBoundColumn DataField="DateTime" DataType="System.DateTime" HeaderText="OrderTime" SortExpression="DateTime" UniqueName="DateTime" AllowFiltering="false"> </radG:GridBoundColumn> </Columns> </MasterTableView> </radG:RadGrid> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="timeOrders" EventName="Tick" /> </Triggers> </asp:UpdatePanel> <asp:Timer ID="timeOrders" runat="server" Interval="10000" OnTick="timeOrders_Tick"> </asp:Timer>
Now, this way it doesn't work as I want because whenever the AsyncPostBack occurs the grid needs to be rebound because otherwise it will be empty. However, as I asked in my very first post in this thread, I'd like to know how/if I can take the grid out of the postback programatically, so when my check says the data is still up to date, it doesn't update in the browser and spare the DOM processing. If I take out the trigger it doesn't work either because then a full postback occurs on every tick.

No comments:

Post a Comment