DetailsView Insert behind the code is not working - c#

I'm trying to insert some data in the database through using
detailsView insert command. And Its not working. Here is my code
behind. I manage to successfully insert in the .aspx page buti has some limitations, since I need to use the row of the gridview as data also and I can only accomplish it if I do it in the aspx.cs page.
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
string Price;
string Item;
string PetitionType;
string Note;
string UserNameGV = (GridView1.SelectedRow.Cells[3].Text);
string InvoiceGV = (GridView1.SelectedRow.Cells[5].Text);
string CreatedDateGV = (GridView1.SelectedRow.FindControl("lblLocalTime") as Label).Text;
SearchTB.Text = UserNameGV + " " + InvoiceGV + " " + CreatedDateGV;
DateTime CreatedDate = Convert.ToDateTime(CreatedDateGV);
for (Int32 attempt = 1; ;)
{
using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["RapidVisaConnectionString"].ConnectionString))
{
try
{
Price = ((TextBox)DetailsView1.Rows[1].FindControl("TextBox2")).Text;
Item = ((DropDownList)DetailsView1.Rows[1].FindControl("DropDownList2")).SelectedValue;
PetitionType = ((DropDownList)DetailsView1.Rows[1].FindControl("DropDownList3")).SelectedValue;
Note = ((TextBox)DetailsView1.Rows[1].FindControl("TextBox2")).Text;
con.Open();
string Sql = "INSERT INTO InvoiceDetail (Price, Item, PetitionType, Note, Paid, Quantity, Invoice, UserName, CreatedDate) VALUES (#Price, #Item, #PetitionType, #Note, #Paid, #Quantity, #Invoice, #UserName, #CreatedDate)";
SqlCommand cmd = new SqlCommand(Sql, con);
cmd.Parameters.AddWithValue("#Price", Price);
cmd.Parameters.AddWithValue("#Item", Item);
cmd.Parameters.AddWithValue("#PetitionType", PetitionType);
cmd.Parameters.AddWithValue("#Note", Note);
cmd.Parameters.AddWithValue("#Paid", 1);
cmd.Parameters.AddWithValue("#Quantity", 1);
cmd.Parameters.AddWithValue("#Invoice", InvoiceGV);
cmd.Parameters.AddWithValue("#UserName", UserNameGV);
cmd.Parameters.AddWithValue("#CreatedDate", CreatedDate);
cmd.ExecuteNonQuery();
return;
}
catch (SqlException sqlException)
{
// Increment Trys
attempt++;
// Find Maximum Trys
// Override the web.config setting of 4 for retrys for this method because we are getting time-out errors.
Int32 maxRetryCount = Int32.Parse(ConfigurationManager.AppSettings["ConnectionRetrys"]);
//Int32 maxRetryCount = 5;
// Throw Error if we have reach the maximum number of retries
if (attempt == maxRetryCount)
{
ErrorLog EL = new ErrorLog();
EL.WriteErrorWithSubjectNoWriteToDB("", "Error InvoiceDetail Max Retry");
//going to stop throwing an error because we are getting too many
//throw;
break;
}
// Determine if we should retry or abort.
if (!SQLUtilities.RetryLitmus(sqlException))
{
ErrorLog EL = new ErrorLog();
EL.WriteErrorWithSubjectNoWriteToDB("Insert Failed RetryLitmus for user " + UserName + ". Sql exception number " + sqlException.Number.ToString() + ". " + sqlException.ToString(), "Error InvoiceDetail Failed Litmus");
//going to stop throwing an error because we are getting too many
//throw;
break;
}
else
Thread.Sleep(SQLUtilities.ConnectionRetryWaitSeconds(4));
//Changed from default of 5 seconds to 3 seconds
//Thread.Sleep(SQLUtilities.ConnectionRetryWaitSeconds(attempt));
}
}
}
}
Here is the error message that I got.
Inserting is not supported by data source 'DetailsViewDS' unless
InsertCommand is specified. The problem is I dont want to add InsertCommand in aspx page , only in aspx.cs

I've tested your code, did some modifications and it works. I've used table of my db, you can modify it according to your need. Modify your SqlDataSource and C# code within DetailsView1_ItemInserting as mentioned below. It will work perfectly.
SqlDataSource:
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM [Image]" InsertCommand="INSERT INTO [Image] ([Name]) VALUES (#Name)">
<InsertParameters>
<asp:Parameter Name="Name" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
Insertion from code behind
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
SqlDataSource sqldsInsertPassword = new SqlDataSource();
sqldsInsertPassword.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
sqldsInsertPassword.ProviderName = ConfigurationManager.ConnectionStrings["ConnectionString"].ProviderName;
sqldsInsertPassword.InsertCommand = "INSERT INTO Image (Name) VALUES (#Name)";
sqldsInsertPassword.InsertCommandType = SqlDataSourceCommandType.Text;
sqldsInsertPassword.InsertParameters.Add("Name", e.Values[0].ToString());
sqldsInsertPassword.Insert();
}
I hope it will solve your issue.
Regards!

Related

Need to update a column in SQL with WHERE using comma separated values from textbox

Just to let you guys know I'm not a programmer # all but I can manage to get code to work sometimes but I'm stumped now. I have a c# web-based project that I finally figured out how to pass comma-separated values from a single textbox to return a result in Datagrid when I click search. The code looks like this:
{
String str = "select row_number() OVER (ORDER BY [sequenceid]) #,[JobNumber],[Item],Quantity,Bay,Trailer,Sequenceid, Produced from vwcabsandcountersbyjob ";
String str1 = "select SUM([Quantity])AS [Items Remaining to Be Loaded] from vwcabsandcountersbyjob";
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str += " WHERE (jobnumber IN ('" + string.Join("','", search.ToArray()) + "') and loaded is null) ORDER BY ITEM DESC";
}
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str1 += " WHERE (jobnumber IN ('" + string.Join("','", search.ToArray()) + "') and loaded is null) ";
}
SqlCommand xp = new SqlCommand(str, vid);
SqlCommand xp1 = new SqlCommand(str1, vid);
//xp.Parameters.Add("#search", SqlDbType.NVarChar).Value = TextBox1.Text;
xp.Parameters.Add("#search", SqlDbType.NVarChar, 20).Value = TextBox1.Text;
xp1.Parameters.Add("#search", SqlDbType.NVarChar).Value = TextBox1.Text;
vid.Open();
xp.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = xp;
DataSet ds = new DataSet();
da.Fill(ds, "[jobnumber]");
GridView1.DataSource = ds;
GridView1.DataBind();
vid.Close();
vid.Open();
xp1.ExecuteNonQuery();
SqlDataAdapter da1 = new SqlDataAdapter();
da1.SelectCommand = xp1;
DataSet ds1 = new DataSet();
da1.Fill(ds1, "[jobnumber]");
GridView2.DataSource = ds1;
GridView2.DataBind();
vid.Close();
}
Now i have a second button that I want to update a field when they press "mark complete". It works fine with a single entry and here is the code:
protected void Button2_Click(object sender, EventArgs e)
{
vid.Open();
SqlCommand xp = new SqlCommand("Update [Job_Master] SET [Completed] = GETDATE() WHERE [job number] =#search", vid);
SqlCommand xp3 = new SqlCommand("Update [Countertops] SET [Completed] = GETDATE() WHERE [jobnumber] =#search", vid);
xp.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp3.Parameters.Add("#search", SqlDbType.NChar).Value = TextBox1.Text;
xp.ExecuteNonQuery();
xp3.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
The problem is it only works for one value. I've tried a million different things but nothing works mainly because I don't know what I'm doing. This is the closest I've come (i added a 3rd button because i didn't want to break button 2 that works for single value):
Protected void Button3_Click(object sender, EventArgs e)
{
String str3 = "Update [Job_Master] SET [Completed] = GETDATE()";
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
List<string> search = new List<string>();
char[] characters = { ',', '\n' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ids.Length; i++)
{
search.Add(ids[i].Trim());
}
str3 += " WHERE [job number] IN ('" + string.Join("','", search.ToArray()) + "')";
}
SqlCommand xp4 = new SqlCommand(str3, vid);
vid.Open();
xp4.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp4.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
and it doesn't work. It only updates when I have a single entry. My question is how do use those same values from that textbox work in an update statement? I hope I'm being clear but will try my best to answer any questions but please remember my vocabulary is very limited when it comes to programming. Thanks!
It would be wise if you just divide your code into smaller parts, group them by their role and responsibility. This would make things much easier to maintain and also to work with.
if you see repetitive code, then it's a flag of moving it to a separate method.
A few notes that I've found in your code :
you should use using clause when possible, like using it with SqlConnection, SqlCommand, and SqlDataAdapter.
Multiple unneeded SqlCommand are used.
Providing SqlParamter while the query doesn't have any parameter.
using string concatenation is not optimal, instead use StringBuilder.
Your business logic should have its own methods or classes, and can be recalled inside any event.
Split returns Array, so no need to convert Array to another Array.
Always, each portion of the code, should be scoped to that portion role only. For instance, OnClick event, should handle the click event only, and not handling the update records. The update part should be declared and handled outside the event, and you only recall it from inside the event.
I have updated the code, which would give you a better view on the above notes:
protected void SearchButton_OnClick(object sender, EventArgs args)
{
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrWhiteSpace(TextBox1.Text))
{
SearchAndBind(TextBox1.Text);
}
}
protected void Button2_Click(object sender, EventArgs e)
{
var textValue = TextBox1.Text.Trim();
if(!string.IsNullOrWhiteSpace(textValue))
{
UpdateRecords("UPDATE [Job_Master] SET [Completed] = GETDATE() WHERE [job number] = #search", "#search", textValue);
UpdateRecords("UPDATE [Countertops] SET [Completed] = GETDATE() WHERE [jobnumber] = #search", "#search", textValue);
CompletedJobNotification();
}
}
protected void Button3_Click(object sender, EventArgs e)
{
string inClause = GetInClause(TextBox1.Text);
if(!string.IsNullOrWhiteSpace(inClause))
{
StringBuilder query = new StringBuilder("Update [Job_Master] SET [Completed] = GETDATE()");
query.Append(" WHERE [job number] ").Append(inClause);
UpdateRecords(query.ToString());
CompletedJobNotification();
}
}
private void PopulateData(string query, string srcTable, GridView gridView)
{
if (!string.IsNullOrWhiteSpace(query))
{
using(SqlConnection connection = new SqlConnection(connectionString))
using(SqlDataAdapter adapter = new SqlDataAdapter(query, connection))
{
adapter.Open();
DataSet ds = new DataSet();
da.Fill(ds, srcTable);
gridView.DataSource = ds;
gridView.DataBind();
}
}
}
private string GetInClause(string text)
{
if(!string.IsNullOrWhiteSpace(text))
{
char[] characters = { ',', '\n' };
var ids = text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
return "IN ('" + string.Join("','", ids) + "')";
}
return string.Empty;
}
private void SearchAndBind(string search)
{
//CODE THAT ALLOWS MULTIPLE ORDER NUMBERS TO BE ENTERED IN A SINGLE TEXTBOX
if (!string.IsNullOrWhiteSpace(search))
{
string inClause = GetInClause(search);
if(!string.IsNullOrWhiteSpace(inClause))
{
var searchWhere = $" WHERE jobnumber loaded IS NULL AND {inClause} ";
StringBuilder str = new StringBuilder("SELECT ROW_NUMBER() OVER (ORDER BY [sequenceid]) #,[JobNumber],[Item],Quantity,Bay,Trailer,Sequenceid, Produced FROM vwcabsandcountersbyjob");
StringBuilder str1 = new StringBuilder("SELECT SUM([Quantity]) AS [Items Remaining to Be Loaded] FROM vwcabsandcountersbyjob");
str.Append(searchWhere).Append(" ORDER BY ITEM DESC ");
str1.Append(searchWhere);
PopulateData(str.ToString(), "[jobnumber]", GridView1);
PopulateData(str1.ToString(), "[jobnumber]", GridView2);
}
}
}
private void UpdateRecords(string query, string parameterName = null,string parameterValue = null)
{
using(var connection = new SqlConnection(connectionString))
using(var command = new SqlCommand(query))
{
if(!string.IsNullOrWhiteSpace(parameterName) && !string.IsNullOrWhiteSpace(parameterValue))
{
command.Parameters.AddWithValue(parameterName, parameterValue);
}
connection.Open();
command.ExecuteNonQuery();
}
}
private void ShowJavaScriptAlert(string message)
{
if(!string.IsNullOrWhiteSpace(inClause))
{
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", $" window.onload = function(){{ alert('{message}')}}; ", true);
}
}
private void CompletedJobNotification()
{
ShowJavaScriptAlert("This job has been marked complete!");
}
Ok, first up, we are writing too much code here.
Next up, we can MOST certainly have a list of parameters, and they can be optional, and we NEVER concatenate user input into the SQL string - we don't have to.
Now, I don't have the users data, lets do this:
I can type in a city, or several. I will display some hotels, and then ONE button to confirm the hotels and update the database with the confirm date.
(the same as what you are doing).
Ok, so a text box, and a button. Like this:
Search: <asp:TextBox ID="txtPromptCity" runat="server" Height="17px" Width="336px"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="Search City" Style="margin-left:20px" />
So, you can type in one city, or several (with a , in between). Same as what you need/are doing.
Ok, so when you type in and hit search, we send the results to a grid view.
So, we have this code for the button:
DataTable rstHotels = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
rstHotels = (DataTable)ViewState["rstHotels"];
}
protected void cmdSearch_Click(object sender, EventArgs e)
{
string[] strChoices;
strChoices = txtPromptCity.Text.Split(',');
using (SqlCommand cmdSQL = new SqlCommand("",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
string strSQL = "";
int i = 1;
foreach (string strCity in strChoices)
{
if (strSQL != "")
strSQL += ",";
i += 1;
strSQL += "#" + i;
cmdSQL.Parameters.Add("#" + i, SqlDbType.NVarChar).Value = strCity;
}
cmdSQL.CommandText = "SELECT * from tblHotels WHERE City IN (" + strSQL + ")";
cmdSQL.Connection.Open();
rstHotels.Rows.Clear();
rstHotels.Load(cmdSQL.ExecuteReader());
ViewState["rstHotels"] = rstHotels;
GridView1.DataSource = rstHotels;
GridView1.DataBind();
}
}
note how I keep/have the data table - I persist it at the class level.
So, our output is now this
Ok, so we now have the parameter issue working.
Now, all you have to do is check box the ones to approve, and then send the data back to the table - along with the approved visit date.
That code NOW becomes dead simple.
We can use this:
protected void cmdConfirm_Click(object sender, EventArgs e)
{
foreach (GridViewRow gvRow in GridView1.Rows)
{
CheckBox chkVisit = (CheckBox)gvRow.FindControl("chkVisit");
if (chkVisit.Checked)
// update Visit date in table
rstHotels.Rows[gvRow.RowIndex]["VistDate"] = DateTime.Today;
// now send table changes back to database.
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels where ID = 0",
new SqlConnection(My.Settings.TEST4)))
{
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daUpate = new SqlCommandBuilder(da);
da.Update(rstHotels);
}
}
}
So, note how we send the grid choices back to the table, and then send the table back to the database. This makes the whole process easy, and VERY much less code.
And I would probably add a 2-3 lines more code in the Row bound event, and set the checkbox if the row has a date already. And we could I suppose even check if we un-check the checkbox, and again null out the date column row.
All of these are VERY dead easy with the above approach.
So, persisting the table as per above - makes this REALLY easy. And note the data Keys setting - we can use/get/grab the primary key of each row and not have to display it - but this example does not see to need this ability anyway.
The markup I used for above is this:
Search: <asp:TextBox ID="txtPromptCity" runat="server" Height="17px" Width="336px"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="Search City" Style="margin-left:20px" OnClick="cmdSearch_Click" />
<div style="width:45%;margin-top:20px;margin-left:20px">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="VistDate" HeaderText="Visit Date" DataFormatString="{0:yyyy-MM-dd}" />
<asp:TemplateField HeaderText="Confirm Visit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkVisit" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="cmdConfirm" runat="server" Text="Confirm Vists" Width="143px" CssClass="btn-info" OnClick="cmdConfirm_Click" />
<br />
</div>
Thanks for all of the help from everyone. The actual was that my aspx code was pointing to OnClick="Button2_Click" and not OnClick="Button3_Click". Once i fixed that and put in the original code it worked. Having said that you guys have pointed out some great points that i'm going to try and fix. Again, i'm not a programmer and sure appreciate you guys helping. Thanks.
First of all, good job getting as far as you did. I think the only thing left is just a simple mistake. I'll provide this which removes a little of the code you don't need
Protected void Button3_Click(object sender, EventArgs e)
{
String str3 = "Update [Job_Master] SET [Completed] = GETDATE()";
// ** This is a little dangerous. If the TextBox is EMPTY, you will be
// ** Updating ALL rows in the table. I assume that is not what you want.
// ** You should return an error if text box is empty.
if (!string.IsNullOrEmpty(TextBox1.Text.Trim()))
{
char[] characters = { ',', '\n' };
char[] invalid = { ',',';',' ','\'','"','\\','\t' };
string[] ids = TextBox1.Text.Trim().Split(characters, StringSplitOptions.RemoveEmptyEntries);
//
// ** You don't really need to copy into a list.
// ** If you want to trim each entry, you can just
// ** replace in the original array.
for (int i = 0; i < ids.Length; i++)
{
ids[i] = ids[i].Trim();
// ** Add a check here to make sure id is safe
// ** to prevent SQL injection.
if (ids[i].IndexOfAny( invalid ) != -1)
{
return; // should give error, probably.
}
}
// *** figure out if it is job_number or jobnumber or (unlikely) job number
str3 += " WHERE [job_number] IN ('" + string.Join("','", ids) + "')";
}
else {
return; // empty string. Should give error.
}
// ** OPEN FIRST
vid.Open();
SqlCommand xp4 = new SqlCommand(str3, vid);
// ** #search not needed
// xp4.Parameters.Add("#search", SqlDbType.VarChar).Value = TextBox1.Text;
xp4.ExecuteNonQuery();
vid.Close();
string message = "This job has been marked complete!";
string script = "window.onload = function(){ alert('";
script += message;
script += "')};";
ClientScript.RegisterStartupScript(this.GetType(), "SuccessMessage", script, true);
}
Now, if the IDs are not supposed to be numeric, you have a little more difficulty preventing SQL injection. You'd want to create a parameter for each one (#1, #2, #3, etc...) and add each as a parameter.
Or, of course, you could run a separate SQL statement for each ID. Not super efficient but probably fast enough.

Prevent Duplicate E-mail Address Submissions c#

I have the following c# code below that I am trying to include additional functionality to prevent duplicate e-mail addresses from being entered into the database using an asp.net form. Below is the code, currently it is inserting all entries, duplicate or not, into the database.
using System.Data.OleDb;
using System.Configuration;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["northwind"].ToString();
con.Open();
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail=' " + TextBox2.Text + "'";
OleDbCommand cmd = new OleDbCommand(query, con);
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
Label1.Text = "email is already in use";
}
else {
cmd.CommandText = "insert into[Table1](pName, pEmail)values(#nm,#em)";
cmd.Parameters.AddWithValue("#nm", TextBox1.Text);
cmd.Parameters.AddWithValue("#em", TextBox2.Text);
cmd.Connection = con;
int a = cmd.ExecuteNonQuery();
if (a>0)
{
Label1.Text = "Inserted Sucessfully!";
}
}
}
}
Asp.net form code
<form id="form1" runat="server">
<div style="height: 138px">
Enter Name:<asp:TextBox ID="TextBox1" runat="server" style="margin-left: 12px"></asp:TextBox>
<asp:RequiredFieldValidator
id="reqName"
ControlToValidate="TextBox1"
Style="color:Red"
ErrorMessage="Please enter your name!"
runat="server" />
<br />
Enter Email:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator
id="ValidEmail"
ControlToValidate="TextBox2"
Style="color:Red"
ValidationExpression="^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"
ErrorMessage="Invalid Email Entry"
runat="server" />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Submit" />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
</div>
</form>
As you are a doing a SELECT statement, you need to the ExecuteScalar method on OleDbCommand to get the results. As per the MSDN documentation, ExecuteScalar returns:
The first column of the first row in the result set, or a null
reference if the result set is empty.
In your case, the return will be the value of COUNT(ID) from your query.
ExecuteNonQuery is for operations which modify data and will return the number of rows affected by the query. As per the MSDN documentation:
You can use the ExecuteNonQuery to perform catalog operations, for
example, to query the structure of a database or to create database
objects such as tables, or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data. For
UPDATE, INSERT, and DELETE statements, the return value is the number
of rows affected by the command. For all other types of statements,
the return value is -1. If a rollback occurs, the return value is also
-1.
So change you code as follows:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail='" + TextBox2.Text + "'"; // note: vulnerable to SQLInjection.
OleDbCommand cmd = new OleDbCommand(query, conn);
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
// etc.
Update: I would also recommend using a Transaction on your operation to make sure that a duplicate email address is not added in between your checking for duplicates and you doing the actual insert.
Update 2:
Based on the updated code that switches to using ExecuteScalar, this line:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail=' " + TextBox2.Text + "'";
Should be:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail='" + TextBox2.Text + "'";
(Extra whitespace character between pEmail=' and " removed.
I think it may be the way you're instantiating the command object, but I'm not in a place to set up a test project to confirm. I think you actually want the ExecuteReader method, or at least that's what I've used in the past for SELECT on the fly like this.
This is what I'm basing it on: OleDbCommand.ExecuteReader
Can you try something like
protected void Button1_Click(object sender, EventArgs e) {
OleDbConnection con = new OleDbConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString2"].ToString();
con.Open();
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= " + TextBox2.Text;
OleDbCommand cmd = new OleDbCommand(query, con);
OleDbDataReader reader = command.ExecuteReader();
int count = 0;
while (reader.Read()) {
count = Convert.ToInt32(reader[0].ToString());
}
reader.Close();
if (count > 0) {
Label1.Text = "email is already in use";
} else {
//re-instantiate the command obj
cmd = new OleDbCommand(); //empty constructor should work, I think
cmd.CommandText = "insert into[Table1](pName)values(#nm)";
cmd.Parameters.AddWithValue("#nm", TextBox1.Text);
cmd.CommandText = "insert into[Table1](pEmail)values(#nm)";
cmd.Parameters.AddWithValue("#nm", TextBox2.Text);
cmd.Connection = con;
int a = cmd.ExecuteNonQuery();
if (a > 0) {
Label1.Text = "Inserted Sucessfully!";
}
}
}
You are trying to check if the email exist with these lines:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= #TextBox2";
int count = cmd.ExecuteNonQuery(query);
but you don't use ExecuteNonQuery to get data from the database, you use ExecuteReader.
Hope this help you with yout issue.
ExecuteNonQuery does not take an argument. Try this:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= #TextBox2";
OleDbCommand cmd = new OleDbCommand(query);
int count = cmd.ExecuteNonQuery();
Also, you are trying to check the return value of ExecuteNonQuery which actually returns the number of rows affected. But that is not the value returned by you SQL statement. If you would like to get the value returned by your SQL statement, you should use ExecuteReader or ExecuteScalar.
And I am not sure if your query is correct either. Shouldn't it be something like:
string query = "SELECT COUNT(ID) FROM Table1 WHERE pEmail= " + TextBox2.Text;

Disappearing items on DropDownList

I'm having an issue with a DropDownList dispaying student names. For some reason it loses items after I click a button, which is used for giving them a grade. I'd like to find a way to preserve these items. The button does not, in any way, filter the students displayed. The resulting DropDownLists should also have autopostback set as true. The student names are not retrieved or altered in the code behind so I'm unsure why the names are disappearing from this DropDownList. Any hints/solutions would be welcome. Update: I have attached code from the front end and also code from the .cs file for the button that sends the mark for the student. After entering a score and going back to the module it was entered for the items disappearing problem arises.
<asp:SqlDataSource
ID="SQLStudentList"
runat="server"
ConnectionString="<%$ ConnectionStrings:UniString %>"
SelectCommand="SELECT DISTINCT students_profile.user_id, (first_name + ' ' + last_name ) AS studentDetails FROM students_profile INNER JOIN classlist ON students_profile.user_id = classlist.user_id INNER JOIN class ON class.class_id = classlist.class_id INNER JOIN student_module_grade ON classlist.classlist_id = student_module_grade.classlist_id INNER JOIN student_module_repeat_grades ON student_module_grade.classlist_id = student_module_repeat_grades.classlist_id WHERE class.pathway_year_id = #idpathway AND student_module_grade.module_on_pathway_id =#modpwayid OR student_module_repeat_grades.module_on_pathway_id=#modpwayid">
<SelectParameters>
<asp:ControlParameter Name="idpathway" ControlID="degreeProgDropDown" Type="String"/>
<asp:ControlParameter ControlID="modDropDown" Name="modpwayid" />
</SelectParameters>
</asp:SqlDataSource>
<asp:DropDownList ID="StudentsList"
OnSelectedIndexChanged="StudentsList_SelectedIndexChanged"
runat="server"
width="420"
AutoPostBack="true"
EnableViewState="true"
DataSourceID="SQLStudentList"
DataTextField="studentDetails"
DataValueField="user_id">
</asp:DropDownList>
protected void Page_Load(object sender, EventArgs e)
{
////If there are no students the message below will be displayed
ListItem selectedItem = StudentsList.SelectedItem;
if (selectedItem != null && !String.IsNullOrEmpty(selectedItem.Text))
{
}
else
{
changedFlag.Visible = true;
changedFlag.Text = "There are currently no grades to change for any students for this module on this pathway";
changedFlag.ForeColor = System.Drawing.Color.Red;
EnterFinalMark.Visible = false;
finalMarkAssignment.Visible = false;
submitAssignmentMark.Visible = false;
repeatSubmitAssignmentMark.Visible = false;
}
if (!IsPostBack)
{
StudentsList.DataSource = SQLStudentList;
StudentsList.DataBind();
String userName = Session["UserLoggedOn"].ToString();
String conString = WebConfigurationManager.ConnectionStrings["UniString"].ConnectionString;
SqlConnection myCon = new SqlConnection(conString);
myCon.Open();
String pathwaySelectionQuery = "SELECT pathway_years.id, pathway_years.pathway_year, pathway FROM pathways INNER JOIN pathway_years ON pathways.id = pathway_years.pathway_id";
SqlCommand pathwaySelectionQuerycmd = new SqlCommand(pathwaySelectionQuery, myCon);
SqlDataReader pwayReader = pathwaySelectionQuerycmd.ExecuteReader();
while (pwayReader.Read())
{
//Put pathway year id in this table instead
degreeProgDropDown.Items.Add(new ListItem(pwayReader["pathway_year"] + ": " + pwayReader["pathway"].ToString(), pwayReader["id"].ToString()));
}
myCon.Close();
}
}
protected void repeatSubmitAssignmentMark_Click(object sender, EventArgs e)
{
String connectionString = WebConfigurationManager.ConnectionStrings["UniString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(connectionString);
myConnection.Open();
String repeatModgradeID = "SELECT repeat_module_grade_id from student_module_repeat_grades WHERE module_on_pathway_id = '" + modDropDown.SelectedValue + "'";
SqlCommand repeatModuleGradeIDCommand = new SqlCommand(repeatModgradeID, myConnection);
Int32 repeatModGradeIDResult = Convert.ToInt32(repeatModuleGradeIDCommand.ExecuteScalar().ToString());
String repeatFindUserID = "SELECT classlist_id from classlist WHERE user_id = '" + StudentsList.SelectedValue + "'";
SqlCommand repeatFindUserIDCommand = new SqlCommand(repeatFindUserID, myConnection);
Int32 repeatClasslistval = Convert.ToInt32(repeatFindUserIDCommand.ExecuteScalar().ToString());
String modOnPwayValue = modDropDown.SelectedValue;
String repeatGrade = finalMarkAssignment.Text;
Int32 repeatGradeval = Convert.ToInt32(repeatGrade);
//Grade is a pass if it is equal to or greater than 40- otherwise it is a fail
if (repeatGradeval >= 40)
{
//Pass assigned to the string which will be added to the table
String passOrFail = "Pass";
//Assigned to label
pOrF.Text = passOrFail;
}
else
{
//Fail assigned to the string which will be added to the table
String passOrFail = "Fail";
//Assigned to label
pOrF.Text = passOrFail;
}
if (repeatGradeval >= 0 && repeatGradeval <= 100)
{
changedVAL.Visible = false;
SqlCommand addAssignmentGradeCommand = new SqlCommand("UPDATE student_module_repeat_grades SET classlist_id=#repeatClasslistid,module_on_pathway_id=#modOnPwayValue,grade=#grade,result_code=#PF,changed=1 WHERE module_on_pathway_id = '" + modDropDown.SelectedValue + "'", myConnection);
addAssignmentGradeCommand.Parameters.AddWithValue(#"modOnPwayValue", modOnPwayValue);
addAssignmentGradeCommand.Parameters.AddWithValue(#"repeatClasslistid", repeatClasslistval);
addAssignmentGradeCommand.Parameters.AddWithValue(#"grade", repeatGradeval);
addAssignmentGradeCommand.Parameters.AddWithValue(#"PF", pOrF.Text);
addAssignmentGradeCommand.ExecuteNonQuery();
myConnection.Close();
success.Visible = true;
ClientScript.RegisterStartupScript(this.GetType(), "alert", "HideLabel();", true);
success.ForeColor = System.Drawing.Color.Green;
repeatSubmitAssignmentMark.Visible = false;
}
else
{
changedVAL.Visible = true;
changedVAL.Text = "Please enter a grade between 0 and 100";
changedVAL.ForeColor = System.Drawing.Color.Red;
}
}
My initial thought it that you are likely not currently checking if a PostBack is occurring or not within the Page_Load event of your Page, which is going to cause your data to be rebound each time.
You can generally resolve this by just performing a check within the Page_Load event itself :
protected void Page_Load(object sender, EventArgs e)
{
// If it is an initial load
if(!IsPostBack)
{
// Then perform your one-time data binding here
StudentsList.DataSource = SQLStudentList;
StudentsList.DataBind();
}
// Business as usual
}

C# Passing Values between dependent Comboboxes

I'm relatively new but I've been researching this issue for over 2 days, so I think I've done my due diligence ... however if this has already been answered before I apologize.
My basic issue is I'm trying to create some dependent combo boxes. The wrinkle is the displayed value is typically not the lookup value for the next query/Combo box (I'm using an OLEDB compliant data base)
For example: Table1 (T1) contains ID (int) & NM (string), Table2 (T2) contains ID (int) & STATUS (string). I run Query1 (Q1) to display T1.NM in Combobox1 (CB1), when selected I run Query1a to lookup/get the selected Table1.ID to pass to Query2 that populates Combobox2. The connection string and Q1 work fine, CB1 displays properly, but once I select this error is thrown:
"OleDbException .. SQL Passthru expression ... using equals (=) has components that are of different data types"
// ** Initial connection & populate CB1 - This works fine **
public void comboboxLoad()
{
string conn3str = <Connection String >;
string query1 = "select NM from Table1 where REFVALUE=1 ; ";
OleDbConnection conn3 = new OleDbConnection(conn3str);
OleDbCommand tblRow1 = new OleDbCommand(query1, conn3);
OleDbDataReader rdRow1;
try
{
conn3.Open();
lblConnState.Text = "Connection Successful";
rdRow1 = tblRow1.ExecuteReader();
while (rdRow1.Read())
{
int colindx1 = rdRow1.GetOrdinal("NM");
string sItbl = rdRow1.GetString(colindx1);
CB1.Items.Add(sItbl);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
// ** Get value from CB1, create query to populate CB2 **
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
conn3.Open();
// Pass the selected value from CB1 (string) equal to Table1.NM (string)
string query1a = "select ID from Table1 where NM = '" + CB1.Text + "' ; ";
OleDbCommand TabID = new OleDbCommand(query1a, conn3);
int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());
// Pass the variable TabId2 (int) equal to Table2.ID (int)
string query2 = "select STATUS from Table2 where ID = '" + TabId2 + "'; ";
OleDbCommand tblRow2 = new OleDbCommand(query2, conn3);
// OleDbDataReader rdTabID;
// OleDbDataReader rdRow2;
try
{
OleDbDataReader rdRow2 = TabID.ExecuteReader();
OleDbDataReader rdTabID = tblRow2.ExecuteReader(); // ** Error points to this line **
while (rdRow2.Read())
{
int TabIdidx = rdTabID.GetOrdinal("ID");
string TabIDVal = rdTabID.GetString(TabIdidx);
// Pass reference ID to label on form
lblBTableID.Text = TabId2.ToString();
int colindx1 = rdRow2.GetOrdinal("STATUS");
string sIntVal = rdRow2.GetString(colindx1);
cmbLowLvl.Items.Add(sIntVal);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}
Are you positive you're getting a value back on this line int TabId2 = Convert.ToInt32(TabID.ExecuteScalar());?
Convert.ToInt32 doesn't throw a ArgumentNullException like int.Parse does so it's possible that the variable is not getting set.
Also you may want to consider changing your queries to use parameterized SQL rather than concatenation for security purposes.
https://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters(v=vs.110).aspx
I've been able to figure out the problem. I'm really not sure why it didn't work originally, but I think it was a reader mismatch, since I was only looking for a single value back from the query ExecuteScalar() seemed to do the trick and I didn't need the 'while' loop. The working code is below.
Next I'll need to pass this return value (ID) in my next query to populate CB2. Thanks #
private void CB1_SelectedIndexChanged(object sender, EventArgs e)
{
string conn3str = <Connection String >;
OleDbConnection conn3 = new OleDbConnection(conn3str);
// Pass the selected value from CB1 (string) equal to Table1.NM (string) but return the int ID.
OleDbCommand tblRow2 = new OleDbCommand("select ID from Table1 where NM= '"+ CB1.Text +"' ;" , conn3);
try
{
conn3.Open();
string r2 = Convert.ToString(tblRow2.ExecuteScalar());
MessageBox.Show(r2);
lblBTableID.Text = "ID Code= " + r2;
conn3.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
}

How to use the GridView AutoGenerateDeletebutton

I am using Visual Studio 2010 to develop an asp.net app using c#. I created an GridView table by the following
<asp:GridView ID="GridView1" runat="server" AutoGenerateDeleteButton="True"
EnableViewState="False" OnRowDeleting="DeleteRowButton_Click">
</asp:GridView>
But I do not know how to use the auto generated delete button in my c# code.
I search online, they always provide my code as
protected void DeleteRowButton_Click(Object sender, GridViewDeleteEventArgs e)
{
var PN = GridView1.DataKeys[e.RowIndex].Values["Part_Number"];
string PN = pn.ToString;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["XMLConnectionString"].ConnectionString);
// Create the command object
con.Open();
string str = "DELETE * FROM XML WHERE ([Part_Numbber] = " + PN + ")";
SqlCommand cmd = new SqlCommand(str, con);
cmd.ExecuteNonQuery();
Button1_Click(sender, e);
con.Close();
}
Thank you very much for anyone can tell me how to do it
For Delete any record from you should have any unique or Primary key. If you want to delete record using field "Part_Numbber" then this field data-type should be of either int or bigint in Database Table. Then Now put the following code to Delete.
protected void DeleteRowButton_Click(Object sender, GridViewDeleteEventArgs e)
{
int Part_Numbber= Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
SqlCommand cmd = new SqlCommand("DELETE FROM XML WHERE Part_Numbber=" + Part_Numbber+ "", con);
con.Open();
int temp = cmd.ExecuteNonQuery();
if (temp == 1)
{
lblMessage.Text = "Record deleted successfully";
}
con.Close();
FillGrid();
}
How this may help you.

Categories

Resources