Slow running web page - asp.net

i created web page with dropdownlist and two gridview and on selectedindex changed event i fill the both of these gridview but in the running the both of gridview take long time to be filled.
Note:one of this gridview i created its datasource by code.
here my code snippet:
protected void _ddlPLCs_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtStatus = new DataTable();
dtStatus = DBLayer.getMachineNameIPStatusPlCByName(_ddlPLCs.SelectedValue);
dtStatus.Columns.Add("Status", typeof(String));
foreach (DataRow row in dtStatus.Rows)
{
if (LogicLayer.checkmachineStatus(row["machineIP"].ToString()))
row["Status"] = "Online";
else
row["Status"] = "offline";
}
GVStatus.DataSource = dtStatus;
GVStatus.DataBind();
if (_ddlPLCs.SelectedValue.Contains('-'))
{
_dsPLCs.SelectParameters.Clear();
_dsPLCs.SelectParameters.Add("PLCID","0");
_dsPLCs.DataBind();
}
else
{
_dsPLCs.SelectParameters.Clear();
_dsPLCs.SelectParameters.Add("PLCID", DBLayer.getPlCIDByName(_ddlPLCs.SelectedValue).ToString());
_dsPLCs.DataBind();
}
}
pleas help me

Looking at the code, I think the problem is in this method:
LogicLayer.checkmachineStatus()
I have a hunch that this actually makes a network request to remote machines/devices to determine their status. This is going to be slow, especially if you have machines that might not be online and you have to wait for them to timeout.
If this is the culprit, what you want to do instead is build a service that runs on your server. The service should continually make these checks in the background and update a database table with the results. You probably want to include a timestamp for the last check in the table. It might even be worth inserting rather than updating, so that you have history of when status's were at different values. Your ASP.Net code should then just show the database table.

Profile! Get a trial version of RedGate ANTS and run it against your code.
If you choose line level timings, it will put a number next to each line in the code that will tell you exactly how long each line takes as a % or in milliseconds. Make sure to use wall clock time not cpu time or wait time from your datasource won't be counted properly.
I'd bet your datasource is slow.

You're doing a lot of work here...
A few random thoughts
Networks can be slow -- #Joel had a good point on that one.
One thing to check would be postback -- make sure you're only databinding on selected index changed.
Why aren't you using a 'handles' caluse in your function? Might not be a problem, just curious.
If you change your "status" column header to "online", and then use checkboxes (checked = online, unchecked = off-line, or something like that, you'll just be updating a bool value for each row, instead of a string value.
Something looks odd about how you're re-binding your dropdownlist. Because... You're using the selected value as a parameter in the gridview. Then you're subsequently re-binding the dropdown list, which potentially will result in a different selected value. Which could be causing your gridview to be databound yet again in a circuit. Not sure, as I can't see all of your code.
Anyway, FWIW. Good luck.

Related

update value only when changed

I had a good look around but couldn't quite find the answer to this one:
I got a Stored Procedure that updates around 30 Fields on a SQL SERVER 2008 Table. It's important for me that one of those Fields is only getting updated, if the value actually changed.
The Stored Procedure Snippet at the moment:
ALTER PROCEDURE test
#p_RoomNo int,
[RoomNo] = #p_RoomNo,
I tried changing it for that particular Column to COALESCE / ISNULL in the SET-Clause of the Procedure, but it still Updates that Column as well
[RoomNo] = COALESCE(#p_RoomNo,RoomNo),
[RoomNo] = ISNULL(#p_RoomNo,RoomNo),
both give me the same Output ...
Do you have any ideas how to NOT Update the Value on Server Side or do I have to put this on a .asp-Forum to change the Application to not pass on any values that are unchanged?
Thanks for any input!
I think the most proper place to check whether the values changed prior to storing the new value is in the asp side of the solution, not in the database. And then you can pass a parameter to the stored procedure.
In the procedure, base on that parameter, you decide whether you should change the value or not.
Edit: Suppose you have a server control of the HiddenField type.
Page_Load(object sender, EventArgs e) {
if (IsPostBack) {
if (myTextBoxIWannaCheckForChanges.Text != myHiddenField.Value) {
// The value has changed.
}
}
}
Note that this will check for changes during the page load. You could also use that kind of logic while handling a button click (if you do so, you don't have to check for a PostBack). Like this:
foo_clicked (object sender, EventArgs args) {
SqlCommand command = // ...snip
// ... set everything you need for your command.
bool changed = (myTextBoxIWannaCheckForChanges.Text != myHiddenField.Value);
command.Parameters.AddWithValue("#changed", changed);
// ... finally let the command execute.
}
Thanks for all replies ...
Changing the Front-End-Application was no option in the end, because changes wouldn't reflect in Future Versions seeing that it's 3rd Party.
I tried most options to alter the SProc but either ran into not getting the desired Field Value updated at all (even when the Value changed) or updating all the times. I decided to look more into the problem from the other side (why I wanted this field not to be updated when the Value didn't change, which was an Update-Trigger, that should only fire when the Value of that Field actually changed.
In the end, the solution was very simple:
Seeing that the
IF UPDATE (RoomNo)
in the Trigger doesn't really compare the Value of the Field but merely if there's an Update called, I simply had to add the comparison via INSERTED and DELETED, so I added the join with DELETED, set my Where Clause on it and it works :)
ALTER trigger [dbo].[UpdateDepartDate]
on [dbo].[Customer]
for update
As
Begin
if update (RoomNo)
Begin
UPDATE Customer
SET [DepartDate] = null
FROM Rooms r
INNER JOIN Customer cu
ON cu.[RoomNo] = r.[Room_ID]
Join INSERTED INS
ON cu.[CU_ID] = INS.[CU_ID]
join Deleted Del
ON INS.[CU_ID] = DEL.[CU_ID]
WHERE INS.[RoomNo] <> DEL.[RoomNo]
END
END
Thought I post it here for anyone interested :)
Thanks again everyone for your help

How should I bind fields from a datasource to a ListView control?

I have a ListView control which I used to populate using an ASP ObjectDataSource control. This worked fine.
However, I wanted to implement a filter that showed items in the ListView that began with the letter A, B, C, etc. To do this, I removed the ObjectDataSource control and replaced it with some code in the Page_Load event allowing me greater control over what I was passing in as the data source, similar to this:
System.Diagnostics.Debug.Print("{0:HH:mm:ss} : GET DATA", DateTime.Now);
List<MyItem> items = GetItems("A"); // Gets a list of items with a description that
// begins with A
MyListView.Datasource = items;
System.Diagnostics.Debug.Print("{0:HH:mm:ss} : BIND DATA", DateTime.Now);
MyListView.DataBind();
System.Diagnostics.Debug.Print("{0:HH:mm:ss} : DONE", DateTime.Now);
Output (times are representative of actual results):
16:00:00 : GET DATA
16:00:00 : BIND DATA
16:00:20 : DONE
Since doing this, it takes about 20 seconds to load the page in my browser, instead of around 1 second when I used the ObjectDataSource.
To load the data into my ListView rows, I use the standard <%# Eval("Description") %> method. After some searching on SO and google, some people seem to say that Eval is inefficient.
Why does manual binding in the Page_Load event slow everything down? Is it because Eval is inefficient? How can I speed it up, and what is the correct way to do this?
It seems highly unlikely to me that the problem is the Eval statement or the the fact that you're databinding in the page load unless your returning a very very large list. Eval may be slower but not by the amount you are seeing. There is probably another cause.
I would double check the GetItems() function. It's more likely that the selection code is somehow less efficient than it could be.
Additional things to check...
Check the properties Eval is calling. Does they do something more that just return a string? Eval will run whatever code is within those properties/methods so make sure they are as fast as possible.
How many records are in your database? Do you have paging enabled? If so, the problem might be that the ObjectDataSource is using a more efficent method to retrieve only the number of objects that it intends on displaying, whereas your call to GetItems() is returning everything, even if it isn't being displayed. Given the huge disparity in the time to return, that is my guess as to what is happening.
If that is what is happening, you speed it up by limiting the number of records you are returning. This is going to depend on your implementation of GetItems(). You'd want to write something like GetItemsPaged(int firstRecord, int pageLength) that returns only a limited amount of data.

ASP.NET page contains dynamic elements, loading takes time

I am dynamically creating a table of checkboxes on my test.aspx page. The dimensions (row and column count) of the table are determined by querying the database.
In test.aspx page, I do the following:
<script language="C#" runat="server">
protected void Page_Load ( object src, EventArgs e ) {
//Query the database to get the data for rows and columns
CheckBox[] chkBox = new CheckBox[rows * columns]; //creates a collection of checkboxes
//Iterate over the query set in a double for loop to create dynamic checkboxes
}
</script>
Right now I have the number of rows=20 and columns=10, but it can increase (with the columns more likely).
I used the Net tab in Firebug to ascertain the time taken by different events and found that GetTest.aspx is taking close to 4 minutes, which is too long a time to wait.
Is there a way to being down the page load time? Is my approach to create dynamic check boxes correct?
Thanks in advance.
cheers
I'm looking at this comment:
// Query the database to get the data for rows and columns
You gloss over this, but 9 times out of 10 when a web page loads slowly it's because it's performing some slow database operation.
My guess is that either (a) you have a very inefficient database query, perhaps due to a lack of indexing, or (b) you're running a database query inside a loop somewhere (very bad).
ASP.NET can create thousands of checkboxes in less than 1 second. It's just class instantiation. The issue is somewhere else.
Enabling ASP.NET trace on the page and see where all the time is spent. Four minutes is of course way too long for any page. You list two though... test.aspx and GetTest.aspx... what is GetTest.aspx?
EDIT:
OK, you are not telling us the whole story here. What else is this page doing? Where are these controls going? I just tried this on a test page using code similar to that above and it renders in a split second.
Like I said... enable TRACE and find out what is really taking up all the time! Use the tool, that's why it's there.
Creation of controls (CheckBox) and adding to a holder from the server-side is very inexpensive. Considering you are not creating billions.
The HTML that is generated should not be big enough to take 4 minutes on a local machine.
Please check the generated HTML size to verify its mass.
If I were you then I would have written the following code on my server. Please consider.
protected void Page_Load(object src, EventArgs e) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
holderPanel.Controls.Add(
new CheckBox {
ID = string.Format("chk{0}{1}", i, j),
Text = "some text"
});
}
}
}
Consider the holderPanel is a server side asp:Panel or a simple Div with ID = "holderPanel" and runat="server"
Try disabling Firebug & see if it still takes that long. Also double check that your code didn't generate more checkboxes than you expected.

Timeout question re. strongly typed datasets and objectdatasources

I have now found a TON of crappy not clear, not relevant examples of ways I can start to tackle the problem. Can't believe i've spent any more than 10 minutes on this but it's been 3 hours so far.
I am looking at an aspx page with next to no code behind. This page renders a crystal report out to a pdf.
The crystal report is bound to an objectdatasource which is bound to one of the tableadapters in a stupidly large dataset.
The problem is the query times out. It's a long running proc, (50 seconds) and timeout is 30 seconds. I have looked at adding a partial class but since the objects are not bound in code i wouldn't be able to set the timeout that way and it's a web site and as such the code behind for the dataset is a whole bunch of XML anyway and i'm not sure I can add a partial class here to expose the time out and if I could i'd be repeating about 70 times, once per adapter.
So does anyone have a better, simpler or at least a method that works so I can get this crystal report, today :)
Thanks
If you are using and ObjectDataSource, you use a partial class to change the command timeout.
Add the following code to the objectCreated event of the ObjectDataSource on the aspx page;
protected void ObjectDataSource1_ObjectCreated(object sender, ObjectDataSourceEventArgs e)
{
DataSet1TableAdapters.DataTable1Adaptor ta;
ta = (DataSet1TableAdapters.DataTable1Adaptor)e.ObjectInstance;
ta.setCommandTimeOut(60);
}
Sory missed the part about the partial classes. Have a look at Control TableAdapter Command Timeout Globally to set the command timeout
Can't you increase the ConnectionTimeout of the SQLCOnnection used to fill the dataset?
i.e. SQlConnection.ConnectionTimeout = somevalue
There are two possibilities: Optimize the procedure or increase your connection timeout.
I know you said it's the command timing out, but I'd bet that it's the connection to the database that is timing out. I've never heard of the command object timing out.
Have you tried changing/setting the time out in the connection string?
If you can't modify the TableAdapter's timeout, and assuming the procedure can't run any quicker, then i don't see any option other than to set the report's data source to the stored procedure directly. Crystal doesn't really care about timeouts that low.

Using DataPager without retrieving all rows on each request

I have a ListView that I am databinding to a collection of objects something like this:
int total;
List<Client> clientList =
clientData.GetClients(criteria, pageNum, pageSize, out total);
uxClientList.DataSource = clientList;
uxClientList.DataBind();
Where the pageNum, pageSize and total parameters facilitate paging at the data access layer. So far so good.
Now I can throw a DataPager on the page, point it at the ListView and get a decent paging UX. There's a little more to it when you're binding programmatically instead of declaratively with a data source control, but the problem here is that DataPager expects that the entire result set is being retrieved each time, from which it should calculate pagination, so it sees the single page of results returned as the total available records and gets rendered as if there is only one page of results available. In other words, the above scenario works fine with DataPager if we switch to a non-paging version of GetClients:
List<Client> clientList = clientData.GetClients(criteria);
uxClientList.DataSource = clientList;
uxClientList.DataBind();
Obviously since our data access layer is kind enough to provide us with a method to retrieve a page at a time, this would be preferable to retrieving all records every time. It would be nice if we could explicitly inform DataPager of the total available records so it could still automatically create pagination output, but only require one page at a time to do so.
I haven't found an easy way to do this and I haven't turned up anything in searches. Admittedly I don't currently posses a deep understanding of the implementation of DataPager, so hopefully I'm overlooking something.
Have a look at the ListViewPagedDataSource and its AllowServerPaging property, I think that may be what you're looking for..
You haven't overlooked anything.
When dealing with large result sets you need to turn paging off and add your own paging controls.
In my experience << < > >> suffice. Nobody goes past the 3rd page anyway.

Resources