Dynamic deletion from SQL database for .NET - c#

I have a SQL database that store values input via a text box. This then displays the values of that database on my output screen via a gridbox. Is there a way I can give the user the an option of which column he wants to delete? Like a delete button near the value in the gridbox.
If not how do I delete a variable column number in SQL. Like, If the user wants to delete line say 10. How do I incorporate that in my SQL delete command.
Should it incorporate the 'top' command? If so how?
protected void Button3_Click(object sender, EventArgs e)
{
SqlConnection sc = new SqlConnection();
sc.ConnectionString = ("Data Source=abc; Initial Catalog=VisualStudioTest; User ID=USER; Password=PASS");
sc.Open();
SqlCommand com = new SqlCommand();
com.Connection = sc;
com.CommandText = ("delete from notes");//initially I've kept this to delete everything.
com.ExecuteNonQuery();
sc.Close();
Response.Redirect(Request.RawUrl);
}
Markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1"
OnSelectedIndexChanged="GridView1_SelectedIndexChanged1">
<Columns>
<asp:BoundField DataField="Notes" HeaderText="Notes" SortExpression="Notes" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:VisualStudioTestConnectionString3 %>"
SelectCommand="SELECT [Notes] FROM [Notes]"
OnSelecting="SqlDataSource1_Selecting">
</asp:SqlDataSource>

i assume your goal is to delete a single row.
the simplest way that comes to my mind is to add a identity field as a key for the table, add the new column to the DataKeyNames list of the GridView and then add a parameter to the DeleteQuery in the SqlDataSource:
delete from notes where identityCol = #identityCol;
the last step is to add the delete control to the Gridview.

Related

I'm trying to make a dropdown list alphabetical order using aspx. Where can I add that in the following code below?

The code here creates a dropdown menu of abbreviations for different location. What I'm trying to do is to get all the abbreviation in alphabetical order. How do I go about doing that?
<asp:DropDownList ID="ddl_loc" runat="server" DataSourceID="CriticalLog"
DataTextField="abbrev" DataValueField="recordKey" Height="16px"
style="margin-bottom: 8px"
ToolTip="Select your Location for updating." AutoPostBack="True"
onselectedindexchanged="ddl_loc_SelectedIndexChanged"
AppendDataBoundItems="True" CssClass="auto-style9" Width="184px">
<asp:ListItem Value="-1">"-- Choose a Location --"
</asp:ListItem>
</asp:DropDownList>
<asp:SqlDataSource ID="CriticalLog" runat="server"
ConnectionString="<%$ ConnectionStrings:CriticalLogConnectionString %>"
SelectCommand="SELECT DISTINCT [name], [recordKey],[abbrev], [phone2], [phone1] , [type] FROM [location] where [name] NOT LIKE '(%' ORDER BY [type],[abbrev]">
</asp:SqlDataSource>
<div class="auto-style6">
<asp:Label ID="lbl_Loc" runat="server" Font-Bold="True" Font-Size="Large"
Font-Underline="True" ToolTip="Location"></asp:Label>
</div>
Well, you useally need (have) some data source for the drop down.
So, say this drop down:
<h3>Select Hotel</h3>
<asp:DropDownList ID="cboHotel2" runat="server"
DataValueField="ID"
DataTextField="HotelName"
Width="288px">
</asp:DropDownList>
Now, to fill above, we go:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadCombo2();
}
void LoadCombo2()
{
string strSQL = "SELECT ID, HotelName FROM tblHotels ORDER BY HotelName";
DataTable rst = MyRst(strSQL);
cboHotel2.DataSource = rst;
cboHotel2.DataBind();
cboHotel2.Items.Insert(0, new ListItem("Please Select", "0"));
}
And now we see this:
So, really, the "common" way to approach this problem, is we order/sort and setup the data BEFORE we sent it to the drop down list.
And I did use that helper routine MyRst, since that just saves a lot of re-typing of code. that helper routine (I usually put in a global set of routines - used it for years). Is this:
public DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
So, be it some list, some table, or whatever data you have to drive the combo box? Sort the data before you SEND the data to the drop down.
Lists, even tables (default view) all have the ability to sort - even if the original source data was not sorted.
Just change your SelectCommand's order by:
SelectCommand="SELECT DISTINCT [name], [recordKey],[abbrev], [phone2], [phone1] , [type] FROM [location] where [name] NOT LIKE '(%' ORDER BY [abbrev]"

GridView Remove one definition

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.

Changing Date Format in Dataset

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..

c# Cannot Convert from string to int

I have a gridview that populates from an SQL table and shows two columns, one comes from an integer data column, the other from an nvarchar. Gridview also has a checkbox column
The gridview populates correctly, and after a subset of rows is selected (via checkbox column) I want to insert the selected rows into another SQL table. When populating the variables for the SQL statement however I get the "Cannot Convert from string to int" error on the value that is populated from an int to begin with.
I have tried writing up convert and parse for this statement but still getting the error:
cmd.Parameters.AddWithValue("#PracticeArea", int.Parse(row.Cells["Id"].Value));
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Value));
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Text));
All still show the error on the ["Id"] value.
Any thoughts?
Example of the data that is being populated to the gridview is:
PracticeID PracticeName
1 General Surgical Pathology
2 General Pathology/Basic Science
4 Cardiovascular
6 Cytopathology-GYN
7 Cytopathology-nonGYN
Full button command is:
protected void Bulk_Insert(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
if ((row.FindControl("CheckBox1") as CheckBox).Checked)
{
string connectionString = WebConfigurationManager.ConnectionStrings["CS1"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
{
using (SqlCommand cmd = new SqlCommand("INSERT INTO ReviewerPractice VALUES(#Reviewer, #PracticeArea)", con))
{
cmd.Parameters.AddWithValue("#Reviewer", ReviewerName.Text);
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Value));
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
}
Full Gridview control is:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Id" HeaderText="Id" ItemStyle-Width="30" />
<asp:BoundField DataField="PracticeName" HeaderText="PracticeName" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
<br />
<asp:Button ID="Button1" Text="Add Practice Areas" OnClick="Bulk_Insert" runat="server" />
Hope this answers (some?) of the questions from all the comments to date.
The problem is that row.Cells[] is an array, so you need to use it like this:
row.Cells[3].Text
And it's better to use the Parameters for sql like this:
cmd.Parameters.Add("#PracticeArea", SqlDbType.Int).Value = Convert.ToInt32(row.Cells[index].Text;

How to bind gridview at pageload with dropdown list

I have a dropdown list to search by categories.
I need help to bind my gridview at page load, but at the same time, I also have a select command as votes.
I know that there are codes such as Databinding in the pageload event. But for my case, i need to link the select command to a button to update votes. If i databind it, i could not grab the data key names to update my votes counter.
Is there any way to bind the gridview, without removing the DataSourceID in the gridview itself?
My aspx codes are as follow.
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM [Review] WHERE ([Category] = #Category)">
<SelectParameters>
<asp:ControlParameter ControlID="ddlCat" Name="Category"
PropertyName="SelectedValue" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [Category] FROM [ReviewCategory]">
</asp:SqlDataSource>
<asp:DropDownList ID="ddlCat" runat="server"
DataSourceID="SqlDataSource2" DataTextField="Category"
DataValueField="Category" AutoPostBack="True"
onselectedindexchanged="SelectionChange">
</asp:DropDownList>
<asp:GridView ID="GridView1" runat="server" Width="1114px"
Height="272px" AutoGenerateColumns="False" PageSize="5"
DataSourceID="SqlDataSource1" AllowPaging="True" DataKeyNames="ReviewID">
<Columns>
<asp:BoundField DataField="Votes" HeaderText="Votes"
SortExpression="Votes" />
<asp:BoundField DataField="Category" HeaderText="Category"
SortExpression="Category" />
<asp:CommandField SelectText="VOTE as your FAVOURITE!"
ShowSelectButton="True" />
</Columns>
c# code
protected void btnVote_Click(object sender, EventArgs e)
{
int reviewid = Convert.ToInt16(GridView1.SelectedDataKey.Value);
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True");
string sqlstmt = "select Votes from Review where ReviewID = '" + reviewid + "'";
SqlCommand comm = new SqlCommand(sqlstmt, conn);
try
{
conn.Open();
SqlDataReader read = comm.ExecuteReader();
if (read.Read())
{
int votes = (int)read["Votes"];
votes += 1;
string updatestatement = "Update Review set Votes= '" + votes + "' Where ReviewID = '" + reviewid + "'";
SqlCommand command = new SqlCommand(updatestatement, conn);
read.Close();
command.ExecuteNonQuery();
}
}
finally {
conn.Close();
GridView1.DataBind();
}
}
protected void SelectionChange(object sender, EventArgs e)
{
int stored = ddlCat.SelectedIndex;
if (stored == 0)
{
SqlDataSource1.SelectCommand = "SELECT * from Review ORDER BY [Votes] DESC ";
}
else { }
}
You should implement the RowCommand event from the GridView. You alredy have the CommandField, so do something like this:
void GridView1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
//
// Get the keys from the selected row
//
LinkButton lnkBtn = (LinkButton)e.CommandSource; //the button
GridViewRow myRow = (GridViewRow)lnkBtn.Parent.Parent; //the row
GridView myGrid = (GridView)sender; // the gridview
int reviewid = Convert.ToInt32(GridView1.DataKeys[myRow.RowIndex].Value); //value of the datakey **strong text**
// If multiple buttons are used in a GridView control, use the
// CommandName property to determine which button was clicked.
// In this case you are pressing the button Select, as ou already
// defined this at the aspx code.
if(e.CommandName=="Select")
{
// Put the logic from btnVote_Click here
}
}
The another way could be implement the SelectIndexChanging or SelectIndexChanged, given that you will use the Select Button to fire the update magic. Here the example with SelectIndexChanging.
void GridView1_SelectedIndexChanging(Object sender, GridViewSelectEventArgs e)
{
// Get the currently selected row. Because the SelectedIndexChanging event
// occurs before the select operation in the GridView control, the
// SelectedRow property cannot be used. Instead, use the Rows collection
// and the NewSelectedIndex property of the e argument passed to this
// event handler.
int reviewid = Convert.ToInt32(GridView1.DataKeys[e.NewSelectedIndex].Value); //value of the datakey **strong text**
// Put the logic from btnVote_Click here
}
Let us look into your requirements one by one:
1.) *Binding GridView at PageLoad with DropDownList:
In this case you need to retrieve the Value selected in dropdownList. Do the below setup to grab the Value from DropDownList
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT [Category] FROM [ReviewCategory] where Category=#Category">
<SelectParameters><asp:ControlParameter ControlID="ddlCat" Name="Category"
PropertyName="SelectedValue" /></SelectParameters>
</asp:SqlDataSource>
What is Happenning:
Each time a value is selected in dropdown, Postback will happen( AutoPostback="true").
After the Page.PreRender Event, the DataSource controls [ SqlDatSource here ] performs the required queries and retrieve the data. So the selected DropDownList value will be used by SqlDataSource. Thus there is NO need to worry about changing/manipulating DataSourceID in any way.
2.) "But for my case, i need to link the select command to a button to update votes"
'
In this case you have a Select button inside grid View and a 'vote' button outside GridView but somewhere in your page. So, once you select any row in grid view, click the 'Vote' button. You can access the SelectedRow and Index as usual.
protected void btnVote_Click1(object sender, EventArgs e)
{
int i = CustomersGridView.SelectedIndex;
}
Note that the Click event of 'Vote' button fires before the DataSource controls perform their queries & retrieve data. So once you update the Vote count in btnVote_click event as you are doing currently, there is NO need to Bind data again. This part of your code seems fine to me.

Categories

Resources