I'm trying to replicate the binding in my markup with something programmatic.
It seems I am forced to use a dataset to bind to rather than a SqlDataSource as shown in my markup.
Furthermore, when using a dataset, I suddenly lose paging, sorting, etc., and get errors that I need to handle them manually.
They were handled automatically before??
So here is my markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True"
CellPadding="4" DataSourceID="SqlDataSource1" ForeColor="#333333"
GridLines="None" AllowPaging="True" AllowSorting="True" Width="520px">
<AlternatingRowStyle BackColor="White" ForeColor="#284775" />
<Columns>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
SelectCommand="CustOrdersOrders" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE" Type="Int32" />
<asp:ControlParameter ControlID="txtCustId" DefaultValue="AROUT"
Name="CustomerID" PropertyName="Text" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
I replaced it with something like this:
SqlDataAdapter adapter = new SqlDataAdapter();
conn.Open();
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlDataAdapter adapter = new SqlDataAdapter();
conn.Open();
using (SqlCommand cmd = new SqlCommand("CustOrdersOrders", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("CustomerID", "AROUT");
cmd.ExecuteScalar();
adapter.SelectCommand = cmd;
}
GridView1.DataSource = adapter;
GridView1.DataBind();
}
This ofcourse raises an error that that the data source is not of the correct type, yet this is exactly what the markup does.
The only thing I can think of is that is uses DataSource instead of DataSourceID.
So how do I replicate this markup and get all the sorting and paging automatically?
If I have to use a dataset, why does the markup not require one?
But, even with the dataset, it doesn't seem to handle the paging and sorting automatically like I said.
Thanks!
Levi
You can not set the DataAdapter as the DataSource property value.SqlDataAdapter provides the communication between the Dataset and the SQL database. You must be using the data adapter to fill a DataTable /DataSet and use that as the DataSource.
Your code had some other problems
1) You are trying to open a connection before declaring it.
2) Sql Data adapter object is created twice with same name.
The below code will work
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlDataAdapter adapter = new SqlDataAdapter();
conn.Open();
DataTable dt = new DataTable();
using (SqlCommand cmd = new SqlCommand("CustOrdersOrders", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("CustomerID", "AROUT");
adapter.SelectCommand = cmd;
adapter.Fill(dt);
}
GridView1.DataSource = dt;
GridView1.DataBind();
}
http://www.dotnetperls.com/sqldataadapter
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldataadapter.aspx
Related
I'm trying to create a web page with the aps.net framework and I connect to the SQL server successfully and I want to display the data from the database in the Grid View and there are a search box and dropdown list but there is an error when I try to search
this is the error message:
Both DataSource and DataSourceID are defined on 'GridView1'. Remove one definition.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Both DataSource and DataSourceID are defined on 'GridView1'. Remove one definition.
and my code viewpage1.aspx
the GridView
<asp:GridView ID="GridView1" runat="server" BackColor="White" BorderColor="#999999" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" Format="dd/MM/yyyy" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="InvoiceID" DataSourceID="SqlDataSource3">
<AlternatingRowStyle BackColor="#CCCCCC" />
-and this the sqldatasource
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:connStr %>" SelectCommand="Select * from [Portal].[fn_GetInvoices] (#SearchText) where CompanyCode=#CompanyCode and InvoiceDate between #fromDate and #toDate">
<SelectParameters>
viewpage1.aspx.cs
sqlcomm.CommandText = sqlquery;
sqlcomm.Connection = sqlconn;
DataTable dt = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(sqlcomm);
adapter.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
This is a common error message.
I OFTEN use the wizards to build a gridview I use this:
From above, I choose create new data source.
I let the wizard run.
BUT THEN we wind up with some MESSAY sqldatasource in the web page. I do NOT like them, and they NEAR ALWAYS just cause you pain.
So, what I will then do this:
Remove the sqldata source from the web markup - you don't' need that mess anyway.
eg this:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:CSharpWebApp.Properties.Settings.TEST4 %>"
SelectCommand="SELECT [ID], [Fighter], [Engine], [Thrust], [Description], [ImagePath]
FROM [Fighters]"></asp:SqlDataSource>
DELETE the above!!!!
Now WHEN you WILL use code to load up the Gridview? Then you ALSO must turn off (remove) the fact that you NOT GOING to use the sql data source anymore.
So in your GV, remove this:
So, all that error message is telling you is you are trying to set the data source in "code" but you ALREADY have a sql datasource setup in the markup.
So, get in the habit of blowing out and removing the sqldata source on the page, and ALSO remove the GV data source setting in the markup.
So, now say I will have this GV, and NOT have ANY data source in the markup in the web page. (and I recommend you do this). So, I still VERY often use the wizards. Even for a dropdown list, a gridview, repeaters, and even listview (my favorite).
So, run wizards - build the markup
Then blow out (remove) the SqlDataSource, and the
DataSourceID="SqlDataSource1" from the control (in this case gv).
So, as noted, you cannot have BOTH a DataSourceID="SqlDataSource1" and THEN try to use code. It is one or the other - and that's what the error message is telling you.
So, now we have this markup:
(and the wizards generated most of this for me!!!)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:ImageButton ID="btnImage" runat="server" Height="68px" Width="149px"
OnClientClick ="popimage(this);return false"
ImageUrl = '<%# Eval("ImagePath") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Just nice clean markup - no Sqldatasource junk.
Now we are free to write normal code like a normal human, and we can fill the grid like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from Fighters", conn))
{
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
And our results are now this:
Ok, so now lets add a search box above the GV to search the GV.
Say you can type in the first few chars of the Fighter jet name, and we want to filter by that:
So, drop in a text box above the GV, + search button.
We now have say this:
<asp:Label ID="Label1" runat="server" Text="Search for Fighter jet" Font-Size="Large"></asp:Label>
<asp:TextBox ID="txtSearch" runat="server" Style="margin-left:15px" Font-Size="Large"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="search"
style="margin-left:15px" CssClass="btn"
/>
<br />
<br />
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
So, now the page with searching looks like this:
Say we search for Lockheed - but even just typing in Lock would be fine.
thus:
And now our code can say be this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid("");
}
void LoadGrid(string MySearch)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from Fighters ", conn))
{
if (MySearch != "")
{
cmdSQL.CommandText += #" WHERE Fighter LIKE #Fighter + '%'";
cmdSQL.Parameters.Add("Fighter", SqlDbType.NVarChar).Value = MySearch;
}
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
protected void cmdSearch_Click(object sender, EventArgs e)
{
LoadGrid(txtSearch.Text);
}
}
So, I am STRONG suggesting that you DUMP the sqldata source on the web page markup. Such Sqldata soruces on the page can be great for one time load or data display. But the VERY instant you want control, filters, and need to use code?
Quite much the SAME instant it is time to drop and toss out and remove the data source from the web markup. You be glad you did, and as you can see, you now have 100% EASY AND SIMPLE control of the data you shove into the GV, and that includes endless possible use of simple code and buttons to add filters etc. to that data.
I have a SQL Server table that has fields with spaces in it. I am attempting to populate an asp datagrid with this information, but on the Bind() event I keep getting an error of
Additional information: A field or property with the name '[Field With Space]' was not found on the selected data source.
I know the field is properly named as if I run it in SSMS it executes properly. Below is my HTML and my C# - what is set-up incorrectly?
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LSTMain"].ConnectionString))
{
cn.Open();
SqlCommand cmd = new SqlCommand("SELECT [Field With Space] FROM [Inventory Log] order by ID ASC", cn);
SqlDataReader dr = cmd.ExecuteReader();
GridView1.DataSource = dr;
GridView1.DataBind();
cn.Close();
}
<div id="dgv">
<asp:GridView ID="GridView1" runat="server" CssClass="Grid" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="[Field With Space]" HeaderText="SQL Field With Spaces" />
</Columns>
</asp:GridView>
you can use the datareader dr.GetString(0)
I tried looking this one up online, but I guess I'm not sure how I should phrase the question without a full explanation.
I've got a webform with a search bar. When you enter in a search term, it queries a database and pulls information and populates a gridview. I'm using the following code:
string find = "SELECT tblShipments.ShipmentID as [Shipment ID], tblShipmentsAssets.DateShip as [Date Shipped], FROM tblShipments INNER JOIN(tblAssets INNER JOIN tblShipmentsAssets ON tblAssets.AssetID = tblShipmentsAssets.AssetIDFK) ON tblShipments.ShipmentID = tblShipmentsAssets.ShipmentIDFK where(AssetIDFK like '%' + #assetidfk + '%' )";
OleDbCommand comm = new OleDbCommand(find, con);
comm.Parameters.Add("#assetidfk", OleDbType.Char).Value = TxtSearch.Text;
con.Open();
comm.ExecuteNonQuery();
OleDbDataAdapter da = new OleDbDataAdapter();
da.SelectCommand = comm;
DataSet ds = new DataSet();
da.Fill(ds, "AssetIDFK");
SearchGridView.DataSource = ds;
SearchGridView.DataBind();
In the past, I've simply populated a gridview solely with aspx code using <asp:SqlDataSource> and there I was able to get at the columns that held dates withing the <columns> tag and add in a DataFormatString="{0:d}" to get the format I wanted:
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" HorizontalAlign="Center">
<Columns>
<asp:BoundField DataField="NextCal" HeaderText="Calibration Due" DataFormatString="{0:d}" >
</asp:BoundField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:Database %>" ProviderName="<%$ ConnectionStrings:Database.ProviderName %>" SelectCommand="SELECT , [NextCal] FROM [tblAssets]"></asp:SqlDataSource>
With my C# method of populating the gridview, I have no <Columns> section to change the data format. I would then assume I need to do this in the code behind, however I'm not sure how to do that.
Figured out what I was doing wrong:
By having <AutoGenerateColumns ="true">, my columns were (big surprise) being automatically generated and then me adding in columns under the tag in .aspx was generating duplicate columns.
I changed it to <AutoGenerateColumns ="false">, manually entered my columns in under the tag and used the DataFormatString="{0:MM/dd/yyyy hh:mm tt}"to change the date format.
Sorry for the dumb question. Hopefully this will help someone avoid the same mistake..
I need to display some data from a view in a SQL Server database on several pages of my website. I've done it by using SqlDataSource within my web.config and then used a GridView control within my .aspx page to display the data.
Now, this works but I read in some forum that it is bad practice to do use SqlDataSource? I will probably need to have the ability for the admin/user to filter the data in the future, so I'm not sure how this would work with my current implementation.
My code so far looks like this :
In the web.config file:
<connectionStrings>
<add name="Test1.ConnectionString"
connectionString="Data Source=...."
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
And something like this in my aspx
<body id="wrap" >
<form runat="server">
<asp:GridView ID="GridView1" runat="server" AllowSorting="True" AutoGenerateColumns="False"
BackColor="White" BorderColor="#CCCCCC"
BorderStyle="None" BorderWidth="1px" CellPadding="3"
DataSourceID="SqlDataSource1" Height="500px" Width="408px">
<Columns>
<asp:BoundField DataField="Title" HeaderText="Title" ReadOnly="True" SortExpression="Title">
<ItemStyle Width="400px" HorizontalAlign="Center" Height="100px" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" />
</asp:BoundField>
<asp:BoundField DataField="Result" HeaderText="Result" ReadOnly="True" SortExpression="Result" >
<ItemStyle HorizontalAlign="Center" Height="100px" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" />
</asp:BoundField>
</Columns>
<FooterStyle BackColor="White" ForeColor="#002756" />
<HeaderStyle BackColor="#003466" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="White" ForeColor="#002756" HorizontalAlign="Left" />
<RowStyle ForeColor="#002756" />
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings: Test1.ConnectionString %>"
SelectCommand="SELECT * FROM [Test1.ConnectionString]">
</asp:SqlDataSource>
</form>
</body>
So my question is is there a better way to implement this, keeping in mind that I will probably need a function for the user/admin to filter the data by certain criteria?
It's not necessarily bad practice to use SqlDataSource... but it does tend to mingle your data access code with your presentation code. Additionally, you can often do better with an ObjectDataSource that wraps your view. There's a little more code involved (you'll have to create a new class somewhere to select from your view), but you end up with methods that can be easily updated or replaced in the future to handle whatever changes you may need.
As mentioned in my comment I would recommend you use the code behind to achieve this as it's much easier to make changes if required in the future. I'm assuming you've got a table in your database named Test1. We'll first create a class to represent this in C# and add a few properties which we'll use later on.
public class Test
{
public string Title { get; set; }
public int Result { get; set; }
}
Now let's create a method which returns a collection of values from your database.
public List<Test> GetData()
{
List<Test> myList = new List<Test>();
string sqlQuery = "Select Title, Result From Test";
string connectionString = ConfigurationManager.ConnectionStrings["Test1.ConnectionString"].ConnectionString; //Read connection string from config file
using (var con = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(sqlQuery, con))
{
//Add param here if required.
con.Open(); //Open connection
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Test t = new Test();
t.Title = reader["Title"].ToString();
t.Result = Convert.ToInt32(reader["Result"]);
myList.Add(t);
}
}
}
}
return myList;
}
Finally, you want to set the datasource for the GridView. I'm going to assume you have a page called MyGridPage.aspx open up the MyGridPage.asps.cs and in your Page_Load event you can set the DataSource for your grid as:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Test t = new Test();
GridView1.DataSource = t.GetData();
GridView1.DataBind();
}
}
If you wanted to filter your Sql query by for example username you'll change it as:
string sqlQuery = "Select Title, Result From Test Where username = #username";
Then you can pass in the #username parameter as:
cmd.Parameters.Add("#username", SqlDbType.NVarChar).Value = myUsername;
myUsername can be of someone who's logged into your app. You will pass the parameter(s) before you open the connection. Passing parameters will also prevent sql injection which I suggest you read up on in case you're not aware.
Note: it is recomenned to make use of using block to ensure the connection object is closed and disposed correctly.
You can programmatically set the data source of the grid view.
protected void Page_Load(object sender, EventArts e)
{
using(SqlConnection conn = new SqlConnection(connectionString))
{
string query = "SELECT * FROM Test"; //your SQL query goes here
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable table = new DataTable();
da.Fill(table);
GridView1.DataSource = table;
GridView1.DataBind();
cmd.Dispose();
da.Dispose();
}
}
I have the following in my .aspx page:
<asp:GridView ID="Table1" runat="server" AutoGenerateColumns="False" BorderColor="Black" OnRowCreated="Table1_RowCreated" OnRowDataBound="Table1_RowDataBound" CellPadding="3" CellSpacing="0" DataSourceID="Table1DataSrc" DataKeyNames="Field1">
<Columns>
<asp:BoundField DataField="Field1" HeaderText="Field1" SortExpression="Field1">
<ItemStyle HorizontalAlign="Left" Font-Size="8" Wrap="false" />
<HeaderStyle CssClass="header" Font-Size="8" />
</asp:BoundField>
</Columns>
</asp:GridView>
Where the gridview has a DataSource that loads a few fields. In my C# code behind, I have the following function which runs a LINQ query to process a stored procedure (on a different server than my other datasource)
private void RenderTables()
{
SqlDataAdapter adapter = new SqlDataAdapter();
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("sp_special", conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#AmIY", "Y");
adapter.SelectCommand = cmd;
adapter.Fill(dt);
adapter.Dispose();
conn.Close();
}
var enumvar = dt.AsEnumerable();
var query = from x in enumvar
orderby x.Field<string>(3)
select new
{
Field3 = x.Field<string>(3),
Field4 = x.Field<int>(4),
};
//I do some data manipulation using LINQ, but omitted here
//do something with query.....
}
How would I add new columns Field3 and Field4 to my Gridview and bind these new records? I do not want to store anything in temp tables on either servers
it will work like this...
<asp:BoundField DataField="Field3" HeaderText="Field3" SortExpression="Field3">
<asp:BoundField DataField="Field4" HeaderText="Field4" SortExpression="Field4">