EntityDataSource Executes the Query twice - asp.net

I have a page that binds data from an EntityDataSource to a paged ASP.NET ListView. The query is actually a fairly complex query and I don't know that an EDS is really the way to go but it's inherited code and I am hoping to resolve this issue without having to re-engineer the page completely.
The problem is that when the page is Posted Back, with a filter parameter, the query executes once without the filter and then once again with the filter. The problem is that the unfiltered resultset is 17+ million records and times the request out.
So my question is ...
Why is the query executing twice? I thought that it might have had something to do with the DataPager on the ListView but when I removed it from the page it didn't change anything.
Update: 2013/04/16
Thank you #bUKaneer and #lthibodeaux. I thought it would behelpful to add the request information to the OP.
As suggested, I commented out Pager control(s) and list view. Upon their removal all requests to the database stopped. I added back just the ListView and the query was executing twice again.
There are no additional event handlers assigned to the EDS itself.
<asp:EntityDataSource ID="edsSerialNumbers" runat="server" ContextTypeName="DBName.Entities" EnableFlattening="False"
EntitySetName="DIST_TABLE" Include="PRODUCT, DISTRIBUTION, DISTRIBUTION.COMPANY_SITE"
EnableUpdate ="true" EnableViewState="true"
OrderBy="it.DISTRIBUTION.DIST_NAME, it.PRODUCT.SERIAL_NUMBER"></asp:EntityDataSource>
The DataPager is actually embedded in a separate UserControl that is included outside of the ListView, and is included twice ...
<div class="dataTablePager">
<kqp:TablePager ID="pgrTop" runat="server" PagedControlID="lvSerialNumbers"/>
</div>
<asp:ListView ID="lvSerialNumbers" runat="server" DataKeyNames="ID" OnDataBound="lvSerialNumbers_DataBound" OnItemEditing ="lvSerialNumbers_ItemEditing" onitemdatabound="lvSerialNumbers_ItemDataBound" EnableViewState="true">
...
</asp:ListView>
<div class="dataTablePager">
<kqp:TablePager ID="pgrBot" runat="server" PagedControlID="lvSerialNumbers"/>
</div>
The only place in the code behind that the EDS is touched is here in the PreRender phase...
protected void Page_PreRender(object sender, EventArgs e)
{
if (!kqpFilters.IsFiltered && !IsPostBack)
{
lvSerialNumbers.DataSourceID = null;
}
else
{
lvSerialNumbers.DataSourceID = "edsSerialNumbers";
}
}

After commenting EVERYTHING out except the spot where the ListView's datasource is assigned to the EDS I was unable to resolve this problem.
I will work around it by ripping out the EDS and replacing it it with a call to a stored procedure instead. Very frustrating though as this problem exists on about 10-15 screens and without an alternative I will have to re-write each, from the ground up.

Related

Good programming practice for Postbacks

newbie to asp.net here. I am building a reporting tool and trying to handle logic on one single page so that report A is one aspx page and so and so forth.
Therefore, many controls / queries actually do not need to get executed on first visit of the page, where only parameters, such as dates, columns, are needed as input.
On clicking a button, or postback i suppose, these controls whether in charts or gridview form would generate. Back in the old dates when I did some ASP programming, I would put all the controls, codes within a if block is see if it is a postback. Is there a more efficient way in doing so in ASP.net?
Thank you all.
Assuming ASP.NET WebForms:
If you need your code to be ran when a button is clicked, you should add your code into your button's click event handler.
<asp:button id="btn" runat="server" text="Submit" onclick="btn_Click" />
protected void btn_Click(object sender, eventargs e){
//code here
}

Submit form to a non default page

I solved this problem in another instance by making some workaround but I want to get it clear this time as I understand my problem better.
My asp.net net page has a search functionality that searches the database based on 5 fields. The result is displayed in the gridview. The gridview is editable and I can update values. The problem is if I want to update multiple values, gridview won't allow it. So I included an extra column for checkbox. I have added a footer which has link to update all checked records.
Ok so here is the problem? How do I send the whole gridview to another page where I can capture the gridview values?
By default the page is submitted onto itself. If I change the default action page, the whole gridview and search, nothing will work.
So how do I submit the whole page (or part of it) to a different page other than the default action script?
I have not tried this specifically with a gridview, but I think a Cross Page PostBack should work. I have a search feature on my website as well and this is what I use.
Set the PostBackUrl of the Button that is causing the PostBack to the Destination page.
Let’s assume your source page is search.aspx and your destination page is SearchResult.aspx
Inside search.aspx:
<asp:Button ID="btnSearch" runat="server" Text="Search" CssClass="right"
ValidationGroup = "Search"
PostBackUrl="~/SearchResult.aspx"
onclick="btnSearch_Click"/>
The form will be posted to SearchResult.aspx. Inside SearchResult.aspx, you add this directive:
<%# PreviousPageType VirtualPath="~/Search.aspx" %>
And in the code behind, you can acess any control like this:
PreviousPage.<mycontrol>
Hope this help.
Have you tried using the Session? Just add the DataSource, or the Gridview itself to the Session and load it in the other Page and then Dispose() it.
Good luck!
UPDATE:
I have accomplished this in the past through Cross-Page Posting. This is how I did it now for testing purposes:
Default.aspx:
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" PostBackUrl="SearchResult.aspx" />
SearchResult.aspx.cs:
protected void Page_Init(object sender, EventArgs e)
{
if (PreviousPage != null)
{
if (Page.PreviousPage.FindControl("GridView1") != null)
{
GridView grid = (GridView)Page.PreviousPage.FindControl("GridView1");
grid.ID = "myGrid";
this.form1.Controls.Add(grid);
}
}
}
Hopefully this helps.

Dynamic dropdownlist in repeater, ASP.NET

Basically, the codes I have is from here : http://ranafaisal.wordpress.com/2009/02/17/dynamically-adding-removing-textboxes-in-aspnet-repeater/
However, the thing is that, I will need a dropdownlist with textboxes. The purpose of having dropdownlist is to allow users to select their country of origin. They have the option to Add or Remove the particulars they have entered before.
This is my error message:
'ddlName' has a SelectedValue which is
invalid because it does not exist in
the list of items. Parameter name:
value
This is my dropdownlist code inside a repeater in Default.aspx
<asp:DropDownList ID="ddlName" runat="server" SelectedValue='<%# DataBinder.Eval(Container.DataItem, "ddl") %>'></asp:DropDownList>
The codes behind is exactly the same as the link I provided.
Points to note: There is no database involved.
Please not tell me to google or anything because I have been googling for the past few hours, to no avail. I definitely have googled enough, and tried the solutions given by others before posting here. I am pretty much at my wits end
To add-on, I cannot even start-up my application because of the dropdownlist problem.
The problem is you need to fill the DropDownList possible options before you set the selected value which you are trying to do inline with the Eval. I would switch it to use the OnDataBinding of the DropDownList and do what you need there.
Example:
<asp:DropDownList ID="ddlName" runat="server" OnDataBinding="ddlName_DataBinding" />
protected void ddlName_DataBinding(object sender, System.EventArgs e)
{
DropDownList ddl = (DropDownList)(sender);
// Fill your ddl here (eg. ddl.Items.Add("abc", xyz");
// Make sure the value you are going to set the selected item to has been added
// Now set the selected value since it will now exist.
ddl.SelectedValue = Eval("ddl").ToString();
}

gridview delete command within updatepanel, and separate __doPostback() functionality

I have a gridview within an updatepanel, the rows have a delete button which removes that row.
Elsewhere, I run code to insert a row. Following this insert I run __doPostback() with the ID of the updatepanel, then in the updatepanel's load() event I call databind() on the gridview.
As soon as I implement the __doPostback() and databind, the inbuilt gridview delete stops working! :( The actual refresh/databind when adding the row works well.
How can I overcome this? I guess something may be awry in that when clicking on the delete button, the databind is conflicting with the inbuild delete/refresh functionality?
Thanks!
EDIT: Apologies if the question isn't described well...
Essentially, I wish to have a gridview with built-in delete functionality through the datasource and command column etc. inside of an updatepanel. I also want to update this panel seperately, but when I put in this separate update code (gridview.databind in the updatepanel.load) it breaks the standard delete functionality. Hope that is clear :)
You've tried put the UpdatePanelMode as Conditional and use UpdatePanel.Update() besides the ClientScript.RegisterStartupScript during your insertion block ?
I believe the problem is that the event is inside of the GridView and you can't access them as easily as you can with something like a Button. To register the GridView to make the Async events you need to attach it to the ScriptManager.
To do this you use the RegisterAsyncpostBackControl method.
Here is a general idea of how to do it.
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server">
<%-- your fields, etc --%>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
In your code behind you do
protected void Page_Load()
{
ScriptManager1.RegisterAsyncPostBackControl(GridView1);
}
It's been a while since I've done this but I believe this will allow the GridView to function as you'd expect, except you don't need the extra DataBind() I don't believe in this case.
You can also set the UpdatePanel to Conditional and fire an UpdatePanel1.Update() on top of this as Jeison suggested.
You can find some added details at http://msdn.microsoft.com/en-us/library/bb386452.aspx
If you still have trouble, let us know what happened.
It seems like you calling DataBind() of GridView every time the UpdatePanel load after the insert button click, it reload the data before delete reaches the DataSource.
EDIT
If so, you can add boolean eventArgument in __doPostBack(updatePanelId, "true"). And using this you could add a condition in your updatepanel load event like
if(this.updatepanel1.Page.Request.Params["__EVENTARGUMENT"] == "true"]
this.gridview.databind()
Hope this will resolve the issue.

How do I maintain viewstate on a user control

I have an ASP Page that uses two listboxes and a third party control (Fluent.ListTransfer) to transfer values from one list to the other. Fairly standard stuff:
<td>
<asp:ListBox ID="ListBoxAvailable" Runat="server"
SelectionMode="Multiple" EnableViewState="true">
</asp:ListBox>
</td>
<td style="vertical-align: middle">
>"/>
<br />
<img src="img/LeftArrow.jpg" alt="<<"/>
</td>
<td>
<asp:ListBox ID="ListBoxSelected" Runat="server"
SelectionMode="Multiple" EnableViewState="true">
</asp:ListBox>
</td>
On the Controls Page_load event, I set the content of the 'available' and 'selected' box with some sql:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
// Some code to work through a recordset, adding values
// to the selected or available list boxes
I assumed that on postbacks, the viewstate would take care of the state of listboxes, as changed by the user (after all, they are standard ASP controls). However, both list boxes are blank if I do a postback.
What's the proper way to maintain the state of the listboxes between postbacks?
Thanks for any help
Ryan
ViewState is like a "spy" on the client side. Whenever there's a change in the client side, the ViewState will report back (read: PostBack) the changes to the server so that the server can re-process the page.
Unfortunately, if we alter contents of a control like ListBox using client-side scripts, ViewState does not see it.
I guess your Fluent.ListTransfer is a client side function.
Some solutions:
The listbox store in ViewState only
the selected item (I guess only the
index), not all the items from list,
so it knows only to restore the
selected item, not the whole list. Is
a little bit strange but is logic. To
mantain in ViewState all the items you
can write a new ListBox derived from
ListBox or HtmlSelect, but you must
handle in the same time the
possibility that the items from list
box be modified on client using
javascript code.
When a page posts back none of the
items in a listbox are sent back to
the server EXCEPT those that are
SELECTED on the client. This makes
sense when you think about it. Forget
about viewstate and all the rest. You
can select multiple items so make all
the items you add to listbox 2
selected.
Another workaround to this, but not so
elegant. The basic idea is to record
all the items on ONE LISTBOX to a
control, and repopulate the listboxes
using the control's value everytime
the page being posted back. Hopefully
somebody could come up with something
better:
Put a HIDDEN input in your web page. Remember to put RUNAT=SERVER
attribute so that you can reference
your input from your ASP.NET code
behind.
In your Javascript, whenever you change the contents of one listbox,
concatenate all the values - using a
separator - and put the value into
your HIDDEN input.
On your Page_Load code, put the code to read the HIDDEN input,
separate the values, and fill in the
listboxes.
Hope this all helps...
If I understand your code correctly you are moving ListItems on the client side from one ListBox to another. But ListBoxes do not submit their whole content - only selected items. So you have to maintain that. I don't know, if Fluent.ListTransfer will do that for you.

Resources