Search

Custom Search

Saturday, April 26, 2008

When To Disable and Enable The Viewstate on a control

Viewstate has a big impact on web performance. If you will not pay attention to it, your website will become a large junk.

How Viewstate does affect performance? Remember that Client and Server Communicates via a postback. And posting a web page as large as 50KB is like uploading a file on youtube or attaching a file on yahoo mail, imagine that. You can check how large is your viewstate when you look at the rendered page by clicking View Source for IE, the part that is garbage looking that occupies almost the whole part of your notepad. Just look at the tag saying __VIEWSTATE.

What really is the function of viewstate? Viewstate is used by ASP.Net to remember the state of the control before a postback occur. One good example is how ASP.Net know that a text has changed when a postback occur or if you have enabled autopostback of the control. It is very simple with the use of viewstate, the value of the textbox is saved on the viewstate, when user changes the value of it and a postback occurs it compares the new value of the textbox and the viewstate if it matches if it does not it raises onChange event.

Now imagine how many controls you have and all of them have viewstate. Each control occupies at list 20 bytes multiply it by the number of your controls. Aside from those, templated and bounded controls like Gridview, Datalist or dropdownlist occupies a very large size of viewstate. But wait we cannot just disable all of them or put enableViewState = false on page directives. What we can do is to use Viewstate wisely.

Here are some pointers I think would help you decide when to disable viewstate.
  • Dynamically inserted value on the controls (By binding or programmatically assigning) – The values of this controls will not retain when it is rerendered, e.g. Switching from view1 to view2. But you have to consider two things, if you think repopulating the values for every render is to heavy to implement then don’t disable the viewstate, if not then you may disable it and reinitialize your controls on render event. Why am I suggesting this? It’s because processing serverside code is much faster than transferring a large junk of data back to the server and unto the client on roundtrips.
  • On Datalist and DropDownList – If you are not using the OnSelectedIndex Change event then you may disable the viewstate.
  • On Gridviews – This is the hardest part to decide whether to disable viewstate or retain it. If you are just displaying data on it or even using it just for selection, then disable the viewstate. If you are using paging, edit or delete functionality then don’t. Gridview has the largest viewstate capacity so you should use it wisely. If you have to update as many as 5 columns then why not just open another view then set the values there to be updated rather than updating it on the gridview directly.

    These are just some of my tips, but you should always test the effect of it so you can see if controls behaves as expected even without viewstate.

Friday, April 18, 2008

Calling A Method By Name

Sometimes we are developing a system that is very much dependent in the database. I call this style as Data Driven Development where everything depends on the database. Even for Buttons that should be available on screen. I have develop a Touch Screen System before using Delphi where Buttons are created Dynamically depending on the set of data returned by the database. This means that each buttons calls its method by function name. To achieve this we set a centralize Event Handler for all Buttons Created Dynamically and then call the routine by Name. That is easy in Delphi for you can call routines of a protected method by Name.
When I shifted to C# I wonder how will I achieve that same functionality. Atlast with some few trials and hard work, I have created a class to handle this. The code is as follows:

public delegate void methodDelegate();
public class FunctionByName
{
private ArrayList
ListOfMethodAddress = new
ArrayList();
private ArrayList
ListOfMethodName = new ArrayList();
public void
AddMethod(methodDelegate
MethodAddress)
{
ListOfMethodName.Add(MethodAddress.Method.Name);
ListOfMethodAddress.Add(MethodAddress);
}

public void ExecMethod(string
MethodName)
{
if
(ListOfMethodName.Contains(MethodName))
{
int MethodIndex =
ListOfMethodName.IndexOf(MethodName);
methodDelegate toExec = new
methodDelegate((methodDelegate)ListOfMethodAddress[MethodIndex]);
toExec();

}
}

}


The difference is that you should add all delegates that you want to be called by name using AddMethod, Then to execute it you call ExecMethod("MyFunction"), Here you are calling MyFunction Method but it should be added initially before you can call it.

Updated: Below is a new version of my CallFunctionByName Class it. It uses Dictionary rather than ArrayList:


public delegate void methodDelegate();
public class
FunctionByName
{
private Dictionary
ListOfMethod = new Dictionary();
public void
AddMethod(methodDelegate
MethodAddress)
{
ListOfMethod.Add(MethodAddress.Method.Name,
MethodAddress);
}
public void ExecMethod(string MethodName)
{
if
(ListOfMethod.ContainsKey(MethodName))
{
methodDelegate toExec =
(ListOfMethod[MethodName]);
toExec();
}
else
{
throw new
Exception("Not yet Implemented");
}
}
}

Tuesday, April 15, 2008

Adding a ROWID() for tables that are linked by UNION ALL

ROW_NUMBER() inserts a virtual ROWID for your query. But how can we create a ROWID for two tables continuously when they are linked using UNION ALL?

Here is How:

(SELECT PartsID AS ItemID, PartsDesc as ItemDesc, ROW_NUMBER()OVER (ORDER
BY PartsID)FROM dbo.Parts)

UNION ALL

SELECT AssemblyID as ItemID, AssemblyDesc,count(PartsID) + ROW_NUMBER() OVER (ORDER BY AssemblyID)FROM dbo.[Assembly],dbo.Parts group by
AssemblyID, AssemblyDesc


Here is how it works:
  1. The first Select Statement inserts a ROW ID for the Parts Table
  2. The Second Select Statement uses two tables (FROM dbo.[Assembly],dbo.Parts). JOINING two tables using From Table1, Table2 multiplies the number of records.
  3. The Second Select Statement was then Grouped By Fields needed for Assembly. This will select the distinct records needed for the query.
  4. count(PartsID) gives the last number of the first query then add it to the ROW_NUMBER() of the second select statement to continue the numbering.
Another way to optimize this is to create a view for the UNION ALL statement then treat it as a single table in your ROW_NUMBER statement.

Adsense Banner