Update Statement Updates 0 Rows via the C# Winform Application? - c#

First of all, please help me out! I can not take this anymore. I could not find where the error is located. Here is my problem:
I'm trying to update a row via c# winform application. The update query generated from the application is formatted correctly. I tested it in the sql server environment, it worked well. When i run it from the application i get 0 rows updated.
Here is the snippet that generates the update statement using reflection - don't try to figure it out. Carry on reading after the code portion:
public void Update(int cusID)
{
SqlCommand objSqlCommand = new SqlCommand();
Customer cust = new Customer();
string SQL = null;
try
{
if ((cusID != 0))
{
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
}
else
{
break;
}
}
}
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
DAL.ExecuteSQL(objSqlCommand);
}
else
{
//AppEventLog.AddWarning("Primary Key is not provided for Update.")
}
}
catch (Exception ex)
{
//AppEventLog.AddError(ex.Message.ToString)
}
}
This part below:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
generates dml:
UPDATE CustomerPhone SET PhoneTypeID = #PhoneTypeID, PhoneNumber = #PhoneNumber WHERE CustomerID = #cusID AND PhoneNumber = '#phNum'
#PhoneTypeID and #PhoneNumber are gotten from two properties. We assigned the value to these properties in the presentation layer from the user input text box. The portion below where fetches the values:
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
The code below fills the values of WHERE:
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
The final code should look as:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = '911';
Phone type id is 7 - user value that is taken from text box
Phone number is 999444 - user value that is taken from text box
The above final update statement works on the sql environment, but when running
via the application, the execute non query runs ok and gets 0 rows updated! I wonder why?

This is the problem:
AND PhoneNumber = '#phNum'
That's looking for a phone number which is exactly the text '#phNum' - it's not using a parameter called phNum. You want
AND PhoneNumber = #phNum
You're also breaking up your string literals for no obvious reason. This statement:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " +
"'" + "#phNum" + "'";
would be more easily readable as:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = '#phNum'";
Obviously you want to drop the single quotes from it, to make it just:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = #phNum";
A little refactoring wouldn't go amiss, either. This loop:
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
would be more simpler and more readable like this:
StringBuilder sqlBuilder = new StringBuilder();
foreach (PropertyInfo property in this.GetType().GetProperties())
{
string name = property.Name;
// I believe you had a bug before - the properties being updated
// would depend on the ordering of the properties - if it
// ran into "TableName" first, it would exit early!
// I *suspect* this is what you want
if (name != cust.PKName && name != "TableName")
{
sqlBuilder.AppendFormat("{0} = #{0}, ", name);
}
}
// Remove the trailing ", "
if (sqlBuilder.Length > 0)
{
sqlBuilder.Length -= 2;
}
You can do something similar with the final loop too.

Is PhoneNumber a string, or an integer?
I see you're SETting as a integer, but checking in the WHERE as a literal. Could this not be the problem?
If it's an integer, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = 911;
If it's a string, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = '999444'
WHERE CustomerID = 500 AND PhoneNumber = '911';

Related

How to insert multiple data into database?

i would like to insert multiple data into my database. I am using for-each statement to get the data and when i insert into the database, it generates 10(just a random no. depending on the no. of data i retrieved) rows for me with one data in every row instead of all in one row. here is the for-each statement i am using.
foreach(var kiev in dict)
{
string na = kiev.Key;
if(na != "db_table_name")
{
string quer = "insert into " + HttpContext.Current.Session["tablename"].ToString() + " ( " + kiev.Key + " ) VALUES ( '" + kiev.Value + "' ) ";
SqlCommand cl = new SqlCommand(quer, con);
cl.ExecuteNonQuery();
}
}
There are better options like "SqlBulkCopy" available as already mentioned in the comments but also something like this should work:
string tablename = "";
string values = "";
string keys = "";
foreach(var kiev in dict)
{
string na = kiev.Key;
if(na != "db_table_name")
{
keys += kiev.Key + ", ";
values += "'" + kiev.Value + "', ";
}
}
keys = keys.Remove(keys.Length - 2);
values = values.Remove(values.Length - 2);
string quer = "insert into " + HttpContext.Current.Session["tablename"].ToString() + " ( " + keys + " ) VALUES ( " + values + " ) ";
SqlCommand cl = new SqlCommand(quer, con);
cl.ExecuteNonQuery();

How to search SQL database and display in C# listview

I need to filter an SQL database using C# to display it in a windowsFormsHost.
For that, I created a text box in which you input the required string. Using this input, the code uses the text to search through the database and display on clicking a refresh button.
The refresh button works and is done, I just need to create the list with the selected rows according to my filter.
Here is the code, which states that no value is returned:
private string GetPassengerList(string sPasssenger)
{
string sPasssengerL = textBoxPassengerName.Text;
if (sPasssenger.Trim().Length > 0)
{
string sToTime = dtpToDate.Value.Year.ToString("D4") + #"/" + dtpToDate.Value.Month.ToString("D2") + #"/" + dtpToDate.Value.Day.ToString("D2");
sToTime += #" " + dtpToTime.Value.Hour.ToString("D2") + #":" + dtpToTime.Value.Minute.ToString("D2") + #":" + dtpToTime.Value.Second.ToString("D2");
string sFromTime = dtpFromDate.Value.Year.ToString("D4") + #"/" + dtpFromDate.Value.Month.ToString("D2") + #"/" + dtpFromDate.Value.Day.ToString("D2");
sFromTime += #" " + dtpFromTime.Value.Hour.ToString("D2") + #":" + dtpFromTime.Value.Minute.ToString("D2") + #":" + dtpFromTime.Value.Second.ToString("D2");
string sSqlSelect = #"SELECT Passenger FROM ";
string sSqlWhere = #" WHERE (Created BETWEEN '" + sFromTime + #"' AND '" + sToTime + #"')";// and (IATA='" + sIata + #"')";
string sSqlLike = #" LIKE '%" + sPasssengerL + "'%";
SqlDataReader sqlReader = null;
try {
SqlCommand sqlCommand = new SqlCommand(sSqlSelect + #"dbo.BagData" + sSqlWhere + sSqlLike, this.dbConnection);
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataHistory" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataArchive" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
if(!sqlReader.Read()) {
sqlReader.Close();
}
}
}
if(!sqlReader.IsClosed) {
sPasssengerL = this.GetSqlDataString(#"Passenger", sqlReader);
sqlReader.Close();
}
}
catch(SqlException x) {
MessageBox.Show(#"GetPassengerName(): SQL Exception: " + x.Message, this.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
catch(Exception ex) {
MessageBox.Show(#"GetPassengerName(): General Exception: " + ex.Message, this.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
finally {
if(sqlReader != null) {
if(!sqlReader.IsClosed) {
sqlReader.Close();
}
}
}
return sPasssengerL;
}
}
You have a few errors in the code you posted.
Using concatenated strings instead of parameters in your sql query.
Re-declaring a variable with the same name as the functions parameter. You are declaring another passenger variable sPasssengerL needlessly in the function now.
Not returning a string value from the function. Your edited code shows the function returning the seemingly unneeded extra passenger variable sPasssengerL now.
Your LIKE statement did not include which column it is checking
against.
I cleaned up the code a little, leaving the sSqlWhere in case that was oddly delcared outside your example. This also shows how to add the first column of data to a listview as you've requested.
EDIT: Per your comment on the original question I've updated the code
to show your sSqlWhere variable.
private void GetPassengerList()
{
string sPassenger = textBoxPassengerName.Text;
if (sPassenger.Trim().Length > 0)
{
string sToTime = dtpToDate.Value.Year.ToString("D4") + #"/" + dtpToDate.Value.Month.ToString("D2") + #"/" + dtpToDate.Value.Day.ToString("D2");
sToTime += #" " + dtpToTime.Value.Hour.ToString("D2") + #":" + dtpToTime.Value.Minute.ToString("D2") + #":" + dtpToTime.Value.Second.ToString("D2");
string sFromTime = dtpFromDate.Value.Year.ToString("D4") + #"/" + dtpFromDate.Value.Month.ToString("D2") + #"/" + dtpFromDate.Value.Day.ToString("D2");
sFromTime += #" " + dtpFromTime.Value.Hour.ToString("D2") + #":" + dtpFromTime.Value.Minute.ToString("D2") + #":" + dtpFromTime.Value.Second.ToString("D2");
string sSqlSelect = #"SELECT Passenger FROM ";
string sSqlWhere = #" WHERE (Created BETWEEN #startDate AND #endDate)";
// I assume this is looking for passenger. Change appropriately.
string sSqlLike = #"AND Passenger LIKE #name";
string searchTerm = "%" + sPassenger + "%";
SqlDataReader sqlReader = null;
try
{
SqlCommand sqlCommand = new SqlCommand(sSqlSelect + #"dbo.BagData" + sSqlWhere, parentWindow.dbConnection);
sqlReader = sqlCommand.ExecuteReader();
if (!sqlReader.Read())
{
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataHistory" + sSqlWhere + sSqlLike;
sqlCommand.Parameters.Add(new SqlParameter("#name", searchTerm));
sqlCommand.Parameters.Add(new SqlParameter("#startDate", sToTime));
sqlCommand.Parameters.Add(new SqlParameter("#endDate", sFromTime));
sqlReader = sqlCommand.ExecuteReader();
if (!sqlReader.Read())
{
sqlReader.Close();
sqlCommand.CommandText = sSqlSelect + #"dbo.BagDataArchive" + sSqlWhere + sSqlLike;
sqlReader = sqlCommand.ExecuteReader();
// This will loop through your returned data and add
// an item to a list view (listView1) for each row.
while (sqlReader.Read())
{
ListViewItem lvItem = new ListViewItem();
lvItem.SubItems[0].Text = sqlReader[0].ToString();
lvItem.SubItems.Add(sqlReader[0].ToString());
listView1.Items.Add(lvItem);
}
sqlReader.Close();
}
}
if (!sqlReader.IsClosed)
{
sPassenger = parentWindow.GetSqlDataString(#"Passenger", sqlReader);
sqlReader.Close();
}
}
catch (SqlException x)
{
MessageBox.Show(#"GetPassengerName(): SQL Exception: " + x.Message, parentWindow.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
MessageBox.Show(#"GetPassengerName(): General Exception: " + ex.Message, parentWindow.GetHashString("Error"), MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (sqlReader != null)
{
if (!sqlReader.IsClosed)
{
sqlReader.Close();
}
}
}
}
}
NOTE: There are other places this code can be cleaned up and simplified but that is beyond the scope of this question.
Check your variables, you've declared sSqlSelect and sSqlLike but not sSqlWhere which you are using in your queries.
a) your function will not compile:
- Missing ";" in several lines,
- local variable declaration "sPessanger" in line 2 conflicts with parameter name ...
b) you never return a value. At least you need a single "return sPassenger;" somewhere in the code to return the selected value.
c) bad style using sql injection. As already stated in the comments, use parameters in your SQL.
d) as far as i can see, you are selecting only a single value from your resultset, or is the GetSqlDataString function supposed to do the job?

Get all items of listbox by converting it in string values

I have listbox and its items are the selected dates from Calendar control in ASP.net. Now I need to filter them in foreach loop according to whether every single date is present database table or not. And the code for same I used is like as:
foreach (string item in ListBoxSelectedDates.Items)
{
string q = "select count(*) from event_calendar where _date='" + Convert.ToDateTime(item).ToString("yyyy-MM-dd") + "'";
MySqlCommand cmd = new MySqlCommand(q, conn);
conn.Open();
if ((long)(cmd.ExecuteScalar() ?? 0) == 0)
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Leave <br>";
i++;
}
else
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Holiday <br>";
i++;
}
conn.Close();
}
And getting error at first line of above code is:
Unable to cast object of type 'System.Web.UI.WebControls.ListItem' to
type 'System.String'.
I am not getting proper solution after continuously trying...
foreach (var _iterator in ListBoxSelectedDates.Items) // here "lstDate" is name of your list where you store all date.
{
string item = _iterator.ToString();
string q = "select count(*) from event_calendar where _date='" + Convert.ToDateTime(item).ToString("yyyy-MM-dd") + "'";
MySqlCommand cmd = new MySqlCommand(q, conn);
conn.Open();
if ((long)(cmd.ExecuteScalar() ?? 0) == 0)
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Leave <br>";
i++;
}
else
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Holiday <br>";
i++;
}
conn.Close();
}
You can use the ListItem.ToString() Method to convert the ListItem to a String.
foreach (var _iterator in ListBoxSelectedDates.Items)
{
string item = _iterator.ToString();
//The rest of your logic here
conn.Close();
}
If you want to access explicitly the value, you can have a look to the ListItem documentation, there you can see that there is a public property called Value so you can use instead:
string item = _iterator.Value;
so you get:
foreach (ListItem _iterator in ListBoxSelectedDates.Items)
{
string item = _iterator.Value;
//The rest of your logic here
conn.Close();
}

Invalid attempt to call Read when reader is closed. getting this error?

Invalid attempt to call Read when reader is closed. getting this error asp.net with c#?
i have used this code
string catalogNo = string.Empty;
string deleteID = string.Empty;
Globals.Initialize("Text", "select CatelogNo,DeleteID from tbl_admin_quotation where QuotationID='" + quotation3 + "' order by id asc");
Globals.dr = Globals.cmd.ExecuteReader();
while (Globals.dr.Read() == true)
{
catalogNo = Globals.dr[0].ToString();
deleteID = Globals.dr[1].ToString();
decimal taqty = 0;
Globals.Initialize("Text", "select qty from tbl_admin_quotation where DeleteID='" + deleteID + "'");
Globals.dr3 = Globals.cmd.ExecuteReader();
if (Globals.dr3.Read() == true)
{
taqty = Convert.ToDecimal(Globals.dr3[0].ToString());
}
Globals.dr3.Dispose();
Globals.dr3.Close();
Globals.Initialize("Text", "select Pqty,Hqty from tbl_admin_stock where CatelogNo='" + catalogNo + "'");
Globals.dr = Globals.cmd.ExecuteReader();
if (Globals.dr.Read() == true)
{
if (Convert.ToDecimal(Globals.dr[0].ToString()) != 0)
{
Globals.Initialize("Text", "update tbl_admin_stock set Pqty=Pqty+'" + Convert.ToDecimal(taqty) + "' where CatelogNo='" + catalogNo + "'");
Globals.cmd.ExecuteNonQuery();
}
else if (Convert.ToDecimal(Globals.dr[1].ToString()) != 0)
{
Globals.Initialize("Text", "update tbl_admin_stock set Hqty=Hqty-'" + Convert.ToDecimal(taqty) + "' where CatelogNo='" + catalogNo + "'");
Globals.cmd.ExecuteNonQuery();
}
}
Globals.dr.Dispose();
Globals.dr.Close();
}
Globals.dr.Dispose();
Globals.dr.Close();
Globals.Initialize("Text", "delete from tbl_admin_quotation where QuotationId=#QuotationId");
Globals.cmd.Parameters.AddWithValue("#QuotationId", quotation3);
Globals.cmd.ExecuteNonQuery();
UpdatePanelMain.Update();
GridviewBind();
If you've code with obvious problems and problems you can't find, fix the obvious problems first and then the obscure problems will likely become obvious:
Get rid of the globals rubbish and put using in the appropriate places and then having the Dispose() called from that rather than explicitly will also fix this problem.

Issues with the update query SQL

am writing a c# code in which am trying to update 4 of the 10 columns of the table. Here is my function type in which am sending arguments for the query:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
Now what happens is that i call this function somewhere in my program providing values in argument:
checkout_visitor(chk_in,chk_out,t_out,dt_out,idcardnum);
The query am using to update my columns is given by:
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = "+ v_idd;
Given me exception incorrect syntax near chkout. Where am i wrong?? is the syntax correct? how do i correct it?
code:
public int checkout_visitor(int check_inn, int checkout, String time_out, String date_out, String cnic)
{
try
{
connection.Open();
String query = "select v_id from visitor where visitor.cnic=" + cnic;
command = connection.CreateCommand();
command.CommandText = query;
visitor_id = command.ExecuteScalar().ToString();
int v_idd = Int32.Parse(visitor_id);
String query2 = " UPDATE visit_detail SET[check_in] = " + check_inn + "[check_out] = " + checkout + "[time_out] = " + time_out + "[date_out] =" + date_out + "where visit_detail.v_id = " + v_idd;
//String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = " + time_out + ",[date_out] =" + date_out + " where visit_detail.v_id = " + v_idd;
command = connection.CreateCommand();
command.CommandText = query2;
int result = command.ExecuteNonQuery();
connection.Close();
return result;
}
catch (Exception e)
{
return -1;
}
}
Problem :
1.you are not seperating the Parameters properly using comma , .
2.you are not giving the sapace between SET and check_in parameter.
Try This:
String query2 = "UPDATE visit_detail SET [check_in] = " + check_inn + ",[check_out] = " + checkout + ",[time_out] = '" + time_out + "',[date_out] ='" + date_out + "' where visit_detail.v_id = "+ v_idd;
Do you see the resulting query? It seems to me you're missing some comma, but you should print (and post) the resulting query to have a better understanding of the issue.
You are missing ',' between the column names.
Its like Update Table Set col1=3,col2='test'
The problem is that query2 string will be something along the lines:
UPDATE visit_detail SET[check_in] = " 1[check_out] = 2[time_out] = some time[date_out] =some datewhere visit_detail.v_id = 5
So you can already see that there's datewhere that is incorect, there are also no ' characters around string parameters, and no commas between parameters.
Quick fix to that would be:
String query2 = String.Format("UPDATE visit_detail SET [check_in]={0}, [check_out]={1}, [time_out]='{2}', [date_out]='{3}' where visit_detail.v_id={4};", check_inn, checkout, time_out, date_out, v_idd);
But this is still not valid. If time_out contains ' characters, you'll again receive an error.
What you should really use is this:
SqlCommand.Parameters
This is a proper way of passing paramters to your command, all the problems will be taken care of for you.

Categories

Resources