Data Source is not supported server side pagination - asp.net

I am working on project which has hundred thousands of records coming from database. I have to show this in DevExpress grid.
Well default behavior of grid is to load all records at once and it applies pagination on client end.
The problem i am having is that the page takes lots of time while loading. To stop this i am going to use server side pagination at devExpress grid. But I am getting error : "The data source does not support server-side data paging"
My grid is "gvList" and i am setting its property as :
gvList.DataSourceForceStandardPaging = True
And then
Dim cmd As New SqlCommand
Dim ds As New DataSet
Dim da As SqlDataAdapter
Dim dbConn As New SqlConnection(conStr)
cmd.CommandType = CommandType.Text
cmd.CommandText = strSQL 'contains SQL string
cmd.Connection = dbConn 'contains connection object
da = New SqlDataAdapter(cmd)
da.Fill(ds, tbl)
gvList.DataSource = ds
gvList.DataBind()
Can any one please tell me where i am going wrong ?
Thanks..
Anjum Dhamial

ASPxGridView supports three different data binding modes:
1) common binding when all data is fetched to the web server and processed by the ASPxGridView itself;
2) server side sorting and paging. This functionality is turned on by activating the ASPxGridView's DataSourceForceStandardPaging property; In this case, you need to use ObjectDataSource since SQLDataSource does not support server side pagination.
3) real server mode when almost grid data related calculations (like grouping, summary) are implemented on the DB server. The link above contains some useful information regarding this mode.
So, the easiest solution to this problem is to use my second option. The third option is much more powerful but will require some additional work.

Use Custom Pagination aproach.
Hence, you should associate the grid to a datasource. It can be a objectdatasource or another.
In datasource, some parameters should be send to class which contains methods for selecting and counting.
An example:
Web form
<asp:ObjectDataSource ID="ds"
EnablePaging="True"
TypeName="Namespace.to.Service"
runat="server"
SelectMethod="FindAll"
SelectCountMethod="FindAllCount"
StartRowIndexParameterName="startRow">
<SelectParameters>
<asp:Parameter Name="maximumRows" Type="Int32" />
<asp:Parameter Name="startRow" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
<asp:GridView ID="grd" runat="server" AutoGenerateColumns="False"
DataSourceID="ds"
AllowPaging="True">
<%-- add columns here --%>
</asp:GridView>
If you need pass extra parameters in datasource from some control, you can add to SelectParameters
<asp:ControlParameter ControlID="txtID" Name="parameterName" PropertyName="Text" Type="String" />
In Namespace.to.Service class, put methods as below:
public IList<MyObject> FindAll(int maximumRows, int startRow) { ... }
public int FindAllCount(int maximumRows, int startRow) { ... }
If extra parameters in datasource was used, simply add them to methods too:
public IList<MyObject> FindAll(int maximumRows, int startRow, string parameterName)
{
/*
fetch result from database or something;
'maximumRows' is pageSize
'startRow' is first result to fetch 'maximumRows' records from database
*/
}
public int FindAllCount(int maximumRows, int startRow, string parameterName)
{
/*
take amount of data for. It will be used to create grid footer for pagination;
parameters are like above.
*/
}
I guess it's all you need.

Related

The Second Time Binding Of ListView raised event Sorting/Editing Exception

I have a ListView which gets filled from search results, and the first time I view the results in the ListView, I can sort as many times as I want with no problem. But when I run another search and hit the search button (which just refreshes the datasource of the ListView to the results) then I get the error:
The ListView 'lvCustomer' raised event Sorting which wasn't handled.
And then if i edit any item again then i get following error:
The ListView 'lvCustomer' raised event ItemEditing which wasn't handled.
I have it reassign the select statement to the sqldata source and rebind the ListView . I do this because if I don't the List displays everything in the database. But I don't think this has anything to do with the error.
First Time I am using object datasource. Second time I am using a dataset. here is the code I am using to rebind it.
protected void btnSearch_Click(object sender, EventArgs e)
{
string name = txtSearch.Text;
DataSet ds = new DataSet();
ds = QMS_BLL.GetCustomers.GetCumtomerByName(name);
if (ds.Tables[0].Rows.Count > 0)
{
lvCustomer.DataSourceID = "";
lvCustomer.DataSource = ds;
lvCustomer.DataBind();
}
}
I simply Edited My Object data-source , and Wrote the second method too into that data source.
<asp:ObjectDataSource ID="odsCustomers" runat="server"
DeleteMethod="DeleteCustomers" InsertMethod="InsertCustomers"
SelectMethod="GetCumtomers" TypeName="QMS_BLL.Customers"
UpdateMethod="UpdateCustomers">
<SelectParameters>
<asp:ControlParameter ControlID="txtSearch" Name="searchName" PropertyName="Text" Type="String" />
</SelectParameters>
I Hope It Will Help Someone Out In Future.Thanks!

How do you filter an ASP.NET Entity Framework Bound ListView via DropDownList?

I am having some trouble figuring out the best way to filter an Entity Framework Query with the results of a DropDownList's Selected Value to fill a ListView Control.
My code is as follows:
Public Function ListViewProducts_GetData() As IQueryable
Dim strVendorName As String = ddlFilterVendor.SelectedValue
Dim myEntities As New InventoryProductsEntities()
Return (From product In myEntities.InventoryProducts
Order By product.ID Ascending
Where product.VendorID = strVendorName
Select product).Take(ddlDisplayRecords.SelectedValue)
End Function
This is pretty rough right now, but I would like to be able to filter this data by vendor, and then page it, but I cannot get the ListView to display the updated queried data. It just continues to display the same data as before, even with a ddlFilterVendor.SelectedValue change.
The drop down list code is as follows:
<asp:DropDownList ID="ddlFilterVendor" runat="server" AutoPostBack="True" DataSourceID="SqlDataSourceVendor" DataTextField="VendorID" DataValueField="VendorID" AppendDataBoundItems="True">
<asp:ListItem Selected="True">All</asp:ListItem>
</asp:DropDownList>
I am stuck at this point.... I was thinking about posting the ddlFilterVendor.SelectedValue to the QueryString and reloading the page, but I would imagine that there should be an easier way to do this. Any help or ideas would be greatly appreciated! Thanks!
The SqlDataSource Code is as follows:
<asp:SqlDataSource ID="SqlDataSourceVendor" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString1 %>" SelectCommand="SELECT DISTINCT [VendorID] FROM [InventoryProducts]"></asp:SqlDataSource>
I have found a solution to this problem. In the DropDownList's SelectedIndexChanged event, I called the following method:
ListViewProducts.DataBind()
This re-queried the database with the appropriate Vendor filter, as shown in code snippet:
Public Function ListViewProducts_GetData() As IQueryable
Dim strVendorName As String = ddlFilterVendor.SelectedValue
Dim myEntities As New InventoryProductsEntities()
Return (From product In myEntities.InventoryProducts
Order By product.ID Ascending
Where product.VendorID = strVendorName
Select product).Take(ddlDisplayRecords.SelectedValue)
End Function
Thanks!

SqlDataSource and stored procedure call issue

I've stumbled upon an issue and can't figure it out on my own. Hope someone could help me resolve it.
So, I have a simple stored procedure in a SQL Server 2005 database
CREATE PROCEDURE spTest
#pin varchar(128)
AS
BEGIN
SELECT #Pin as Param
END
and an asp.net page with a SqlDataSource and a GridView control in an application (VS2008)
<asp:SqlDataSource
ID="sds2"
runat="server"
ConnectionString="..."
SelectCommand="spTest"
SelectCommandType="StoredProcedure"
>
<SelectParameters>
<asp:QueryStringParameter Name="pin" QueryStringField="pin" DbType="String"/>
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="gv" runat="server" DataSourceID="sds2"></asp:GridView>
As you can see, the code is straightforward. Nevertheless, if I don't bother specify the pin on the url (.../Default.aspx instead of .../Default.aspx?pin=somevalue) or specify an empty line (.../Default.aspx?pin=) there is no any call to the stored procedure (I check it with SQL Server Profiler).
Moreover, if I replace the QueryStringParameter with a simple
<asp:Parameter Name="pin" DbType="String" />
and do not point out DefaultValue value, the situation repeats and no calls to the stored procedure are made. What is the reason of such a behaviour?
I'm quite a new to the asp.net and possibly overlook something, but I even tried to do the same in code-behind file programmatically instead of declaratively and the result is the same. The only thing I could find out is that in such case a Selecting event of the SqlDataSource is fired, but the Selected is not. Maybe some kind of an error happens?
Anyway, any kind of help would be greatly appreciated.
The SqlDataSource object has a property called CancelSelectOnNullParameter. Its default value is true, so I think the behavior you're seeing is expected, albeit not obvious. Try setting this property to false.
<asp:SqlDataSource
ID="sds2"
runat="server"
ConnectionString="..."
SelectCommand="spTest"
SelectCommandType="StoredProcedure"
CancelSelectOnNullParameter="false"
>
Additionally, you may find the ConvertEmptyStringToNull property of the Parameter class (QueryStringParameter extends this) to be of some use, depending on if/how your stored proc handles null values. Its default value is true as well.
Try this out.
Create a method which will return db null if parameter is not passed in the stored procedure
public static object GetDataValue(object o)
{
if (o == null || String.Empty.Equals(o))
return DBNull.Value;
else
return o;
}
Create a method which will called the stored procedure and fill the dataset.
public DataSet GetspTest(string pin)
{
try
{
DataSet oDS = new DataSet();
SqlParameter[] oParam = new SqlParameter[1];
oParam[0] = new SqlParameter("#Pin", GetDataValue(pin));
oDS = SqlHelper.ExecuteDataset(DataConnectionString, CommandType.StoredProcedure, "spTest", oParam);
return oDS;
}
catch (Exception e)
{
ErrorMessage = e.Message;
return null;
}
}
Now bind the dataset to gridview
private void GvTest()
{
DataSet oDsGvspTest = new DataSet();
string pin = Request.QueryString["Pin"];
oDsGvspTest = GetspTest(pin);
if (oDsGvspTest.Tables[0].Rows.Count > 0)
{
Gv.DataSource = oDsGvspTest;
Gv.DataBind();
}
}
Now called this method on page_load event
if(!IsPostBack)
{
GvTest();
}
If found it useful,please mark it as your answer else let me know...

How bind single record data to controls in ASP.NET?

Which is the best control/approach in ASP.NET 4 to bind data from single record, which is fetched from sql server? I have some page to display text, so I need labels like title, date of publication, content and so on - single label for each data. Of course I can use ListView or Repeater, but I wonder if there's some other way.
Thanks in advance
You could use the DetailsView, which is designed to display a single record (though it's usually used in a master-details scenario). DetailsView can use SqlDatasource.
Trivial example:
<asp:SqlDataSource id="slqDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:MyConnectionString %>"
SelectCommand="SELECT * FROM Table" />
<asp:DetailsView id="detailsView1" runat="server"
AutoGenerateRows="true" DataKeyNames="Id"
DataSourceID="sqlDataSource1" />
The above example creates a DetailsView based on the SelectCommnad of the SqlDataSource. In the implementation above, since AutoGenerateRows is set to true the control will render the data. However, you can also specify the fields explicitly, and have different fields you can choose from (BoundField, ButtonField, CheckBoxField, etc).
DetailsView Class
sqldatareader is a good one.
you can create a sql-command, and then use the .executereader method. For example:
dim myReader as SqlDatareader
Dim myCommand As New SqlCommand("myStoredProcedure", myConnection)
With myCommand
.CommandType = CommandType.StoredProcedure
With .Parameters
.Clear()
.AddWithValue("myParameter", parametervalue)
End With
End With
Try
myConnection.open
myReader = myCommand.ExecuteReader
While myReader.Read
Me.myTextBox.Text = myReader("fieldname")
Me.myCheckbox.Checked = myReader("fieldname")
End While
Catch ex As Exception
Response.Write(ex.Message)
Finally
myConnection.Close()
End Try
or some such...
You can not bind data to a textfield. However, using a reader like the one listed above creates a WHOLE bunch of unneeded overhead. Why not create a class?
This way you fetch it in your DAL and then do some processing (or conversion) in your BLL.
Be the way I would do it anyways. DataReaders and DataSets should not be used unless you are binding.

Error: SelectedValue which is invalid because it does not exist in the list of items

I have a Gridview which binds to an ObjectDataSource (objStudentDetails). In edit/insert mode of the Gridview one of the fields is a DropDownList that gets it's pick list options from a lookup table. I have this DropDownList binding to another ObjectDataSource control (objStateList) which represents the lookup table. It works fine as long as the value in the objStudentDetails ObjectDataSource matches one of the values in the objStateList ObjectDataSource, at least in the case of a non empty string value anyway.
The objStateList has these values (from the stored proc that loads it - ID#6 is an empty string ''):
StateId State
----------- -----
6
4 AL
1 GA
3 KY
2 TN
The objStudentDetails has these values (from the stored proc that loads it):
FirstName LastName State
----------- ---------- -----
tone smith TN
Or it could have this result set (State is an empty string - ''):
FirstName LastName State
----------- ---------- -----
jenny johnson
In the first objStudentDetails resultset the state DropDownList in the EditItemTemplate shows up fine. In the second resultset, however, I get this error:
'ddlEditState' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value
I would think that since my lookup table has a value with an empty string, that the objStudentDetails value with an empty string for state would match, but something isn't working the way I am expecting it to.
Here is my EditItemTemplate code from the Gridview:
<EditItemTemplate>
<asp:Panel ID="panEditState" runat="server">
<asp:DropDownList ID="ddlEditState" runat="server" CssClass="GridviewDropdownlist"
DataSourceID="objStateList" DataTextField="State" DataValueField="State"
SelectedValue='<%# Bind("State") %>'
Width="50px">
</asp:DropDownList>
</asp:Panel>
</EditItemTemplate>
And the objStateList, which calls a method passing a parameter of which lookup table to query:
<asp:ObjectDataSource ID="objStateList" runat="server" SelectMethod="GetDropdownData" TypeName="AIMLibrary.BLL.DropdownData">
<SelectParameters>
<asp:Parameter Name="itemsToGet" DefaultValue="state" />
</SelectParameters>
</asp:ObjectDataSource>
Any ideas?
Start by setting both DropDownLists' AppendDataBoundItems property to true. Next, add the NULL ListItem by adding the following <asp:ListItem> element to each DropDownList so that the declarative markup looks like:
<asp:DropDownList ID="Categories" runat="server"
DataSourceID="CategoriesDataSource" DataTextField="CategoryName"
DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'
AppendDataBoundItems="True">
<asp:ListItem Value="">[nothing selected]</asp:ListItem>
</asp:DropDownList>
I suspect there are many different scenarios that can cause this error. In my case, I had a drop down placed in a template field. The drop down was bound to its own objectdatasource, and its selectedvalue property was bound to a field from the gridview's own (separate) datasource.
Now, with my specific scenario, the problem was a race condition. The gridview's datasource was being populated and bound BEFORE the dropdowns had their turn. This also meant that the dropdowns' selectedvalues were being set BEFORE the dropdowns' items had been created through their own bindings.
I'm sure there's got to be a better solution, but I didn't have much time for research. I disconnected the gridview and the dropdowns from their datasources (meaning, removing the assignments from the designer) and opted bind programmatically. That way, I can explicitly bind the dropdowns so that their items' values will be available when the gridview itself is bound.
So far, so good. Just a few extra lines of code in the Page_Load
AppendDataBoundItems="True"> works but not in all cases. Making dropdownlist inside GridView is still a mystery which Microsoft has to resolve. They say development is ASP is much quicker than PHP. Well this is my third day on this small problem and still have no solution.
OK, since this is a common problem I guess its worth to actually post an answer: After a lot of looking around I've found two solutions - well, one patch and one real one.
Patching:
Set the DDL setting AppendDataBoundItem=true anda add manually one element to the list (i.e. "Please Select" with null value):
< asp:DropDownList ID="DropDownList5 runat="server" AppendDataBoundItems="True" ... >
< asp:ListItem>Please Select< /asp:ListItem>
< /asp:DropDownList>
This seems to work in about 80% of cases. I had a weird situation when I had to upgrade existing (and working) query used by DDL to allow another value of parameter - Query was something similar to SELECT ID, Name from EMPLOYEES where Department =#Department and originally #Department could only be equal to "Planners" and "Workshop" - after adding "Logistics" DDL mysteriously stopped working ONLY for the new value of department.
Proper solution: Bind the DDL during the GridView_RowDataBound event (fount thanks to This article
My parameter is taken as a text from the label (set up somewhere else)
protected void GridView5_RowDataBound(object sender, GridViewRowEventArgs e)
{
//********** this is a workaround for the annoying problem with dropdownlist in gidview without adding new item ************
if (e.Row.RowType == DataControlRowType.DataRow && GridView5.EditIndex == e.Row.RowIndex)
{
DropDownList DropDownList5 = (DropDownList)e.Row.FindControl("DropDownList5");
string query = "SELECT gkey as empID, name FROM [employees] where department=#department";
SqlCommand command = new SqlCommand(query);
command.Parameters.AddWithValue("#department", lblDepartment.Text);
DropDownList5.DataSource = GetData(command);
DropDownList5.DataTextField = "name";
DropDownList5.DataValueField = "empID";
DropDownList5.DataBind();
}
And the GetData method:
private DataTable GetData (SqlCommand cmd)
{
string strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(strConnString))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataTable dt= new DataTable())
{
sda.Fill(dt);
return dt;
}
}
}
}

Resources