SQL delete command? - c#

I am having trouble with a simple DELETE statement in SQL with unexpected results , it seems to add the word to the list??. Must be something silly!. but i cannot see it , tried it a few different ways. All the same result so quite confused.
public void IncludeWord(string word)
{
// Add selected word to exclude list
SqlConnection conn = new SqlConnection();
String ConnectionString = "Data Source = dev\\SQLEXPRESS ;" + "Initial Catalog=sml;" + "User id=** ;" + "Password =*;" + "Trusted_Connection=No";
using (SqlConnection sc = new SqlConnection(ConnectionString))
{
try
{
sc.Open();
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
Command.Parameters.AddWithValue("#word", word);
Command.ExecuteNonQuery();
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
finally
{
sc.Close();
}
ExcludeTxtbox.Text = "";
Box.Text = " Word : " + word + " has been removed from the Exclude List";
ExcludeLstBox.AppendDataBoundItems = false;
ExcludeLstBox.DataBind();
}

Try removing the single quotes. Also why are you concatenating your SQL string with a connection object (.. word='#word'" + conn)???
Try like this:
try
{
using (var sc = new SqlConnection(ConnectionString))
using (var cmd = sc.CreateCommand())
{
sc.Open();
cmd.CommandText = "DELETE FROM excludes WHERE word = #word";
cmd.Parameters.AddWithValue("#word", word);
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
...
Notice also that because the connection is wrapped in a using block you don't need to Close it in a finally statement. The Dispose method will automatically call the .Close method which will return the connection to the ADO.NET connection pool so that it can be reused.
Another remark is that this IncludeWord method does far to many things. It sends SQL queries to delete records, it updates some textboxes on the GUI and it binds some lists => methods like this should be split in separate so that each method has its own specific responsibility. Otherwise this code is simply a nightmare in terms of maintenance. I would very strongly recommend you to write methods that do only a single specific task, otherwise the code quickly becomes a complete mess.

SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
should be replaced with
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'",
conn);
Also try by removing single quotes as suggested by others like this
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word=#word",
conn);

The #Word should not be in quotes in the sql query.
Not sure why you're trying to add the connection on the end of the sql query either.

To debug this, examine the CommandText on the SqlCommand object. Before reading further, you should try this.
The issue comes with adding the single quotes around a string that is parameterized. Remove the single quotes and life is beautiful. :-)
Oh, and your conn is an object and needs a comma, not a +.

See the code below:
private void button4_Click(object sender, EventArgs e)
{
String st = "DELETE FROM supplier WHERE supplier_id =" + textBox1.Text;
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
MessageBox.Show("delete successful");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
private void button6_Click(object sender, EventArgs e)
{
String st = "SELECT * FROM supplier";
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
SqlDataReader reader = sqlcom.ExecuteReader();
DataTable datatable = new DataTable();
datatable.Load(reader);
dataGridView1.DataSource = datatable;
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}

See the code below:
String queryForUpdateCustomer = "UPDATE customer SET cbalance=#txtcustomerblnc WHERE cname='" + searchLookUpEdit1.Text + "'";
try
{
using (SqlCommand command = new SqlCommand(queryForUpdateCustomer, con))
{
command.Parameters.AddWithValue("#txtcustomerblnc", txtcustomerblnc.Text);
con.Open();
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
MessageBox.Show("Error");
MessageBox.Show("Record Update of Customer...!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
con.Close();
loader();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
con.Close();
}

You can also try the following if you don't have access to some of the functionality prescribed above (due, I believe, to older versions of software):
using (var connection = _sqlDbContext.CreatSqlConnection())
{
using (var sqlCommand = _sqlDbContext.CreateSqlCommand())
{
sqlCommand.Connection = connection;
sqlCommand.CommandText = $"DELETE FROM excludes WHERE word = #word";
sqlCommand.Parameters.Add(
_sqlDbContext.CreateParameterWithValue(sqlCommand, "#word", word));
connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
...
I'm an associate dev. Hence the "I believe" above.

Related

How to Query Return Value on using Compact SQL Command?

I using a compact database created on visual studio. just for a stand alone system with it's database intact already although i'm stuck here in using a select query that could retrieve a boolean if the user exist on the database and also then return it's ID and Username if the user entry exist. can i ask for help regarding on this one.. I am a student trying to learn c# on using compact database.
private void btnLogin_Click(object sender, EventArgs e)
{
try
{
if (!IsEmpty())
{
if (!IsLenght())
{
using (SqlCeConnection con = new SqlCeConnection("Data Source=" +
System.IO.Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), "INCdb.sdf")))
{
con.Open();
SqlCeCommand cmd = con.CreateCommand();
cmd.CommandText = "SELECT * FROM LoginTB Where username=#user1 AND password=#pass1";
cmd.Parameters.AddWithValue("#user1", UserTxt.Text.Trim());
cmd.Parameters.AddWithValue("#pass1", PassTxt.Text.Trim());
cmd.CommandType = CommandType.Text;
validlogin = (bool)cmd.ExecuteScalar();
con.Close();
MessageBox.Show(validlogin.ToString());
if (validlogin == true)
{
// cmd. return value ID
// cmd. return value Username
//SysMain Mn = new SysMain();
//Mn.ShowDialog();
//this.Hide();
}
}
}
}
}
catch (Exception ex)
{
gbf.msgBox(1, ex.Message.ToString(), "");
}
}
The code below is probably better, unless there is something special and unstated about the schema of LoginTB.
// ...
var validLogin = false;
using (SqlCeConnection con = new SqlCeConnection(
"Data Source=" +
System.IO.Path.Combine(
Path.GetDirectoryName(
System.Reflection.Assembly.GetEntryAssembly().Location),
"INCdb.sdf")))
{
con.Open();
SqlCeCommand cmd = con.CreateCommand();
cmd.CommandText =
"SELECT COUNT(*) FROM LoginTB Where username=#user1 AND password=#pass1";
cmd.Parameters.AddWithValue("#user1", UserTxt.Text.Trim());
cmd.Parameters.AddWithValue("#pass1", PassTxt.Text.Trim());
cmd.CommandType = CommandType.Text;
validlogin = ((int)cmd.ExecuteScalar()) > 0;
}
MessageBox.Show(validlogin.ToString());
// ...
Note the use of COUNT

Can't retrieve data from SqlDataReader in C#

I need to insert values into several tables first I have to retrieve university id from table college and then insert faculty name into table faculty and get generated by SQL Server ID. After all of this I have to insert both ids into an other table.
Problem is that I have to close readers and after I do it I can't retrieve those ids from them so variable where they should be saved is null. Here is my code. How to do it correctly?
Sorry I am new to C# and SQL Server.
// reading data into combobox
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
comboBox1.Items.Add(myReader["name"].ToString());
// Console.WriteLine(myReader["Column2"].ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
myConnection.Close();
private void button1_Click(object sender, EventArgs e)
{
string item = comboBox1.Text.ToString();
// MessageBox.Show(item);
SqlConnection myConnection = new SqlConnection("user id=bogdan_db;" +
"password=1234;server=localhost;" +
"Trusted_Connection=yes;" +
"database=cafedrascience; " +
"connection timeout=30");
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
// reading data into combobox
String colegeid = null;
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
myReader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
String facultyid = null;
try
{
SqlDataReader myReader1 = null;
SqlCommand myCommand = new SqlCommand("select * from depart where name like'" + textBox1.Text + "'",
myConnection);
myReader1 = myCommand.ExecuteReader();
while (myReader1.Read())
{
facultyid = myReader1["id"].ToString();
}
myReader1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
SqlCommand myCommand1 = new SqlCommand("INSERT INTO coledge_faculty (coledge_id, faculty_id) " +
"Values ('"+colegeid+"''"+facultyid+"')", myConnection);
myCommand1.ExecuteNonQuery();
// MessageBox.Show(colegeid);
// MessageBox.Show(facultyid);
myConnection.Close();
}
The number one thing I can stress about your code is that you should be using parameterised queries, beyond the obvious risks of SQL Injection, it also protects you against malformed SQL, data truncation through conversion, and it allows you to use cached execution plans.
The next thing to point out is that you should not be using SELECT * in production code, e.g.
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
Why bother retrieving all the columns of colege from the database, then sending them all over the network if you only care about the column id?
Finally your diagnosis of the problem is not correct:
Problem is that I have to close readers and after I do it, I can't retrieve those ids from them, so variable where they should be saved is null
If you assign the string variable colegeid a value you have retrieved from a data reader, it will not be null after you have closed the reader, it will retain the value you assigned. The most likely reason the variable is null is because your reader returns no rows so you never assign it a value.
Now, rant over, I will actually answer your question. You are massively over complicating the issue, you do not need to retrieve the values into your application tier only to insert them to another table, you can do this all in a single query in your database:
INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;
Then it would just be a case of calling this SQL from C#:
string item = comboBox1.Text.ToString();
string connectionString = "user id=bogdan_db; password=1234;server=localhost; Trusted_Connection=yes; database=cafedrascience; connection timeout=30";
string sql = #"INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#Colege", SqlDbType.VarChar, 50).Value = item;
command.Parameters.Add("#Depart", SqlDbType.VarChar, 50).Value = textBox1.Text;
connection.Open();
command.ExecuteNonQuery();
}
It is usually a good idea to use using blocks with objects that implement IDisposable, this will ensure the resources are freed up when you are done with them (Don't confuse this with not being able to reuse the connection, .NET has connection pooling in the background so it will reuse connections for you, you shouldn't keep your SqlConnection object open available in case you need to use it again).
On another unrelated note, I also think you are too liberal with try/catch blocks, or at least not dealing with the exception properly, using this one as an example:
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
If myConnection.Open() does throw an error, you still carry on with the method. You will carry on until you get to here:
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
Where you will get another exception, something along the lines of the command requiring an open and available SqlConnection, so you go to the exception.
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Again you don't exit the method, but carry on, and you will get the same error later when you try and use the connection again. Again the method carries on and you will use the closed connection a third time to try and insert two variables that were never assigned because exceptions were thrown into your database. Fine, use try catch blocks, but do something meaningful with the exception and exit the method.
private void BtnAdd_Click(object sender, EventArgs e)
{
//con.Open();
cmd = new SqlCommand("INSERT INTO TBL_STORE VALUES (N'"+txt_store_name.Text.Trim()+"',N'"+txt_store_adress.Text.Trim()+"',N'"+txt_store_mobile_1.Text.Trim()+"',N'"+txt_store_mobile_2.Text.Trim()+"',N'"+txt_store_Manger.Text.Trim()+"',N'"+txt_store_Details.Text.Trim()+"')");
cmd.Connection = con;
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#store_name", txt_store_name.Text.Trim());
cmd.Parameters.AddWithValue("#store_adress", txt_store_adress.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_1", txt_store_mobile_1.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_2", txt_store_mobile_2.Text.Trim());
cmd.Parameters.AddWithValue("#store_manger", txt_store_Manger.Text.Trim());
cmd.Parameters.AddWithValue("#store_details", txt_store_Details.Text.Trim());
cmd.Parameters.AddWithValue("#Id_store", txt_store_number.Text.Trim());
con.Close();
lbl_store.Text="insert is sucess";
//cmd.Parameters.Add("#store_name", SqlDbType.NVarChar, 50).Value = txt_store_name.Text.Trim();
}

Why won't my code write to SQL?

I'm writing an app to store texts to an SQL database, but my code throws an exception saying "the variable name #par1 has already been declared", I'm not sure how to get this working and would like some help fixing this if possible please =]
offending code is below
private void SMSGetter()
{
try {
DecodedShortMessage[] messages = Comm.ReadMessages(PhoneMessageStatus.All, PhoneStorageType.Sim);
SqlConnection Conn = new SqlConnection("Data Source=*********;Initial Catalog=********;User ID=**********;Password=***********");
SqlCommand com = new SqlCommand();
com.Connection = Conn;
Conn.Open();
foreach (DecodedShortMessage message in messages)
{
//com.CommandText = ("INSERT INTO SMSArchives(Message,Blacklist) VALUES ('" + message.Data.UserDataText + "', 'Yes')");
//com.ExecuteNonQuery();
com.CommandText = ("INSERT INTO SMSArchives(Message,Blacklist) VALUES (#par1,#par2)");
com.Parameters.AddWithValue("#par1", message.Data.UserDataText);
com.Parameters.AddWithValue("#par2", "Yes");
com.ExecuteNonQuery();
}
Conn.Close();
}
catch (Exception ex) {
Log(ex.ToString());
}
}
You are using the same command for every iteration, but adding parameters each time. Try calling
com.Parameters.Clear();
at the end of each loop iteration. You could also pre-create the parameters and just set the .Value per iteration - probably marginally faster.
Also: fix the SQL injection hole :)
private void SMSGetter()
{
Log("Getter Fired");
//var message = GSM.ReadMessage(4);
//GSM.ReadMessage(4);
//TcpClientChannel client = new TcpClientChannel();
//ChannelServices.RegisterChannel(client, false);
//string url = "*******";
//ISmsSender smssender = (ISmsSender)Activator.GetObject(typeof(ISmsSender), url);
try
{
DecodedShortMessage[] messages = Comm.ReadMessages(PhoneMessageStatus.All, PhoneStorageType.Sim);
SqlConnection Conn = new SqlConnection("Data Source=*********;Initial Catalog=********;User ID=**********;Password=***********");
SqlCommand com = new SqlCommand();
com.Connection = Conn;
Conn.Open();
com.CommandText = ("INSERT INTO SMSArchives(Message,Blacklist) VALUES (#par1,#par2)");
com.Parameters.Add("#par1");
com.Parameters.Add("#par2");
foreach (DecodedShortMessage message in messages)
{
com.Parameters["#par1"].value = message.Data.UserDataText;
com.Prepare(); //fix SQL injection :)
com.ExecuteNonQuery();
}
Conn.Close();
}
catch (Exception ex)
{
Log(ex.ToString());
}
}
You are adding the parameters at every iteration in foreach. Consider the following:
com.CommandText = ("INSERT INTO SMSArchives(Message,Blacklist) VALUES (#par1,#par2)");
command.Parameters.Add(new SqlParameter("#par1", ""));
com.Parameters.AddWithValue("#par2", "Yes");
foreach (DecodedShortMessage message in messages)
{
command.Parameters["#par1"].Value = message.Data.UserDataText;
com.ExecuteNonQuery();
}

C# SQL Server CE - Update won't work

I'm trying to finish a college project that requires a program to interact with a database.
Some of my naming is a little odd, but don't worry!
I'm trying to use a single submit button to either update or insert to the database.
Main issue is that I can't get an update to work though when I changed my code to try and fix it, I made it worse. Here is what I currently have.
private void btn_submit_Click(object sender, EventArgs e)
{
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=G:\Dropbox\HND\Visual Studio\Visual C#\TestForms\TestForms\Database1.sdf"))
{
con.Open();
string taskSel = "SELECT TaskCode FROM TaskCode;";
SqlCeCommand c1 = new SqlCeCommand(taskSel, con);
SqlCeDataReader reader;
reader = c1.ExecuteReader();
if (reader.Read())
{
try
{
string taskUpdate = "UPDATE TaskCode SET TaskCode = #TaskCode, TaskDescription = #TaskDescription = WHERE TaskCode = #TaskCode;";
SqlCeCommand c = new SqlCeCommand(taskUpdate, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record has been updated");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
else
{
try
{
string taskInsert = "INSERT INTO TaskCode VALUES (#TaskCode, #TaskDescription);";
SqlCeCommand c = new SqlCeCommand(taskInsert, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record has been added");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
}
}
Has anyone got any ideas why I am getting an error on the c.ExecuteQuery line?
If I remove said line, it will not throw an exception, but it will not update the database.
Thanks
You have a simple syntax error in your update query just before the where statement.
There is an invalid equal sign
string taskUpdate = "UPDATE TaskCode SET TaskCode = #TaskCode, " +
"TaskDescription = #TaskDescription " +
"WHERE TaskCode = #TaskCode;";
Your query also could be simplified with
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=G:\Dropbox\HND\Visual Studio\Visual C#\TestForms\TestForms\Database1.sdf"))
{
con.Open();
string taskSel = "SELECT COUNT(*) FROM TaskCode";
string cmdText;
SqlCeCommand c1 = new SqlCeCommand(taskSel, con);
int count = (int)c1.ExecuteScalar();
if (count > 0)
{
// Here there is no point to update the TaskCode. You already know the value
// Unless you have a different value, but then you need another parameter
// the 'old' TaskCode.....
cmdText = "UPDATE TaskCode SET " +
"TaskDescription = #TaskDescription " +
"WHERE TaskCode = #TaskCode;";
}
else
{
cmdText = "INSERT INTO TaskCode VALUES (#TaskCode, #TaskDescription);";
}
try
{
SqlCeCommand c = new SqlCeCommand(cmdText, con);
c.Parameters.AddWithValue("#TaskCode", cbx_taskCode.Text);
c.Parameters.AddWithValue("#TaskDescription", txt_desc.Text);
c.ExecuteNonQuery();
MessageBox.Show(count > 0 ? "Record has been updated" : "Record has been added");
MainMenu.Current.Show();
this.Close();
}
catch (SqlCeException exp)
{
MessageBox.Show(exp.ToString());
}
}
Not sure if it is the only problem, but you have an equal (=) sign before the WHERE keyword.

C# update statement with extract

I get error message :
IErrorInfo.GetDescription failed with E_FAIL(0x80004005)
I think in the code is not any variable that needs [] or?
I was searching and everybody has something to do with [].
string queryString = "SELECT sum(skupaj) FROM cas where sifra = " + textBox1.Text + " and EXTRACT(MONTH FROM Datum) = "+textBox2.Text+"";
try
{
OleDbConnection conn = GetConnection();
OleDbCommand command = new OleDbCommand(queryString, conn);
conn.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
ure = reader.GetValue(0).ToString(); ;
}
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
if you just want a sum of something, you dont need a datareader. simply do this:
try
{
OleDbConnection conn = GetConnection();
OleDbCommand command = new OleDbCommand(queryString, conn);
conn.Open();
int count = (Int32) command.ExecuteScalar();
conn.Close();
}
Try to put the table name inside a square bracket like [CAS]. This kind of problem happens if you are using a reserved word in ODBC sql or you are using a field that has space in between then you have to put the field inside a pair of ticks like 'field name'.

Categories

Resources