I am trying to insert the text inside some text boxes into a database that I have in access. The code produces no errors but does not seem to add the items to the database.
The Database is called 'Database' the table is called 'TotalPlayerName' and the field is called 'Player Name'.
There are other fields in the table.
for(int i = 0; i < numberOfPlayers; i++){
using (OleDbConnection connection = new OleDbConnection(#"CONNECTION STRING"){
using (OleDbCommand command = new OleDbCommand(#"INSERT INTO TotalPlayerName ([Player Name]) VALUES(#p1)", connection)){
connection.Open();
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = Convert.ToString(textBox[i].Text);
command.ExecuteNonQuery();
}
}
}
You might just need to declare #p1 because you call it in the INSERT statement, but it is never defined as a variable such as: varchar, int, ect, ect. This might work for what you are trying to do:
using (OleDbCommand command = new OleDbCommand(#"DECLARE #p1 VARCHAR(50) INSERT INTO TotalPlayerName ([Player Name]) VALUES(#p1)", connection)){
Also if at all possible i would definitely make it a stored procedure if you can. This works with SQL not sure if it will work with MS Access, but i would imagine so. The other thing you might want to do is make sure that it's finding the correct DB.
Database.dbo.TotalPlayerName
But that is probably not the issue, probably just the lack of variable declaration.
While I don't see what's specifically wrong with your code, I can tell you your methodology is off a bit. Specifically, for every iteration of your loop you are:
Establishing a connection to the database
Creating the insert command, creating a parameter and assigning the value
Executing the insert
It would be better all around if you did steps 1 and part of 2 once and then executed the statement within the loop like this:
using (OleDbConnection conn = new OleDbConnection(
#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\foo.accdb"))
{
conn.Open();
OleDbCommand command = new OleDbCommand(
#"INSERT INTO TotalPlayerName ([Player Name]) VALUES (#p1)", conn);
command.Parameters.Add(new OleDbParameter("#p1", OleDbType.VarChar));
for (int i = 0; i < numberOfPlayers; i++)
{
command.Parameters[0].Value = textbox[i].Text;
try
{
command.ExecuteNonQuery();
}
catch (Exception ex)
{
// do something
}
}
conn.Close();
}
I assume textbox is an array or list of actual Text Box controls. If that's the case, then textbox[i].Text is already a string, and you shouldn't need to do anything special to make OLE recognize it as such.
On a final note -- add that try/catch and put a breakpoint there. Are you SURE it's not failing? If you are running in debug mode, there is no guarantee that your program will halt -- it may just return back to the form without reporting any error. It may not be until you attempt to deploy the app that you see the actual error occurring.
Related
What am I doing wrong?
I am working on creating a windows forms C# application that is database centered. In my forms app I have 4 textboxes that inserts its data into one simple Database table.
If i type something into textBox1(Customer_Name), and I click on a button called "Check and Save', I would like the action to check if the Customer_Name exists.
If it does not exist, it should insert the data into the database.
If it does exist, it should update my database with the information entered into textBox1-4
I have this code:
private void Button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = new SqlCommand("IF NOT EXISTS (SELECT * FROM [Customers] WHERE Customer_Name=#aa BEGIN INSERT INTO [Customers](Customer_Name,Cellphone_Number,Telephone_Number,Alternative_Number) VALUES(#aa,#bb,#cc,#dd) END ELSE BEGIN UPDATE [Customers] SET Customer_Name=#aa, Cellphone_Number=#bb, Telephone_Number=#cc, Alternative_Number=#dd END", con);
cmd.Parameters.AddWithValue("#aa", textBox1.Text);
cmd.Parameters.AddWithValue("#bb", textBox2.Text);
cmd.Parameters.AddWithValue("#cc", textBox3.Text);
cmd.Parameters.AddWithValue("#dd", textBox4.Text);
con.Close();
}
No information gets entered into the database on button click not does any information update.
What am I doing wrong?
You are not executing the command.
Your code should have a cmd.ExecuteNonQuery(); once the command is fully configured.
However, once you add that, you will get a syntax error message from SQL Server.
This is because you are missing a closing parenthesis for the Exists operator.
Please note that is far from being the only thing you are doing wrong in this code:
you are mixing UI code with application code.
you are using a global variable (or at the very least a field) to hold your instance of the SqlConnection.
you are using terrible names for your parameters and texboxes.
You are using AddWithValue.
the pattern for "upsert" you are using is cumbersome and potentially problematic.
Here are better alternatives:
First
You should read about the n-tier architectural pattern.
For winforms, it's usually implemented using MVP.
For one thing, instead of sending textboxes data directly into your database, create a Customr class to hold the data, and use that to pass customer data around in your code.
Second
Best practice is to use a local variable inside a using statement to ensure disposale of the SqlConnectioninstance and the return of the underlying connection to the connection pool.
Third
Imagine having to change something in a code that looks like this vs. changing something in a code that looks like that:
cmd.Parameters.Add(#"CustomerName", SqlDbType.NVarChar).Value = customerName;
Now you don't have to read at the SQL to figure out what that parameter means -
the less time and effort you have to spend understanding the code the better.
Fourth
The article in the link explains why it's problematic in details,
but the main point is that the data type of the parameter must be inferred from usage,
and that might yield errors because of data type wrongly inferred - or even worst - wrong data silently entered into the database.
Fifth
A better pattern is to first update, and then insert conditionally - like demonstrated in Aaron Bertrand's answer here - and in a multi-user (or multi-threaded) environment wrap the entire thing in a transaction.
All that being said, a revised code should look more like this:
private void AddOrUpdateCustomer(Customer customer)
{
// Data validity tests omitted for brevity - but you should ensure
// customer has all it's properties set correctly.
// Readable, properly indented code - Isn't that much easier to debug?
var sql = #"
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE [Customers]
SET
Cellphone_Number = #Cell,
Telephone_Number = #Telephone,
Alternative_Number = #Alternative
WHERE Customer_Name = #Name
IF ##ROWCOUNT = 0
BEGIN
INSERT INTO [Customers](Customer_Name, Cellphone_Number, Telephone_Number, Alternative_Number)
VALUES(#Name, #Cell, #Telephone, #Alternative)
END
COMMIT TRANSACTION;";
// connectionString should be obtained from configuration file
using(var con = new SqlConnection(connectionString))
{
using(var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add(#"Name", SqlDbType.NVarChar).Value = customer.Name;
cmd.Parameters.Add(#"Cell", SqlDbType.NVarChar).Value = customer.Cellphone;
cmd.Parameters.Add(#"Telephone", SqlDbType.NVarChar).Value = customer.Telephone;
cmd.Parameters.Add(#"Alternative", SqlDbType.NVarChar).Value = customer.AlternativeNumber;
con.Open();
cmd.ExecuteNonQuery();
}
}
}
I checked your code there are few problems.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
con.Open();
SqlCommand cmd = new SqlCommand("IF NOT EXISTS (SELECT * FROM [Customers] WHERE Customer_Name=#aa BEGIN INSERT INTO [Customers](Customer_Name,Cellphone_Number,Telephone_Number,Alternative_Number) VALUES(#aa,#bb,#cc,#dd) END ELSE BEGIN UPDATE [Customers] SET Customer_Name=#aa, Cellphone_Number=#bb, Telephone_Number=#cc, Alternative_Number=#dd END", con);
cmd.Parameters.AddWithValue("#aa", textBox1.Text);
cmd.Parameters.AddWithValue("#bb", textBox2.Text);
cmd.Parameters.AddWithValue("#cc", textBox3.Text);
cmd.Parameters.AddWithValue("#dd", textBox4.Text);
cmd.ExecuteNonQuery();
con.Close();
}
There is a missing bracket and condition is missing in update statement. I have fixed the query. You can try again and also check the SQL Connection string.
IF NOT EXISTS (SELECT * FROM [Customers] WHERE Customer_Name=#aa) BEGIN INSERT INTO [Customers](Customer_Name,Cellphone_Number,Telephone_Number,Alternative_Number) VALUES(#aa,#bb,#cc,#dd) END ELSE BEGIN UPDATE [Customers] SET Customer_Name=#aa, Cellphone_Number=#bb, Telephone_Number=#cc, Alternative_Number=#dd WHERE Customer_Name=#aa END
Insert Data
Update Data
I have not check the SQL statement.
But can you check the code after adding, because without Executing the command Database you can not see changes.
cmd.ExecuteNonQuery();
before
con.Close();
I have a for loop that collects the data from my C# web form and writes each item that it finds to a database via a stored procedure.
The problem I'm having is that it's writing to the database only once. I have stepped through the code in visual studio and inserted test variables to check that all the data is there and is being captured, which it is. Also because the stored procedure is executing correctly the first time I know that it's working.
So I think the problem might be with how I've got the try catch in the for loop?
Or possibly something else entirely - I could really do with a fresh pair of eyes and someone to point me in the right direction!
protected void log_hd_number()
{
////write results to DB.
SqlConnection conn = new SqlConnection("Data Source=;Initial Catalog=;Integrated Security=True");
SqlCommand cmd = conn.CreateCommand();
SqlDataReader reader;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "insert_requested_hd";
Dictionary<String, String> hdSize = new Dictionary<String, String>();
hdSize.Add("hardDiskSizeData1", hardDiskSizeData1.Text);
hdSize.Add("hardDiskSizeData2", hardDiskSizeData2.Text);
int numberRequested = 2;
for (int i = 1; i <= numberRequested; i++)
{
cmd.Parameters.AddWithValue("#hd_size", hdSize["hardDiskSizeData" + i]);
cmd.Parameters.AddWithValue("#number_requested", numberRequested);
cmd.Parameters.AddWithValue("#vm_id", 15);
try
{
conn.Open();
reader = cmd.ExecuteReader();
reader.Close();
}
catch (Exception exc)
{
}
finally
{
if (conn.State != ConnectionState.Closed)
conn.Close();
}
}
}
EDIT:
SP:
ALTER PROCEDURE [dbo].[insert_requested_hd]
-- Add the parameters for the stored procedure here
#hd_size nvarchar(150),
#number_requested int,
#vm_id int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO dbo.hard_disk_size
(
hd_size,
number_requested,
vm_id
)
VALUES
(
#hd_size,
#number_requested,
#vm_id
)
you keep adding parameters to cmd in the loop without ever clearing the old ones. Maybe that's the issue.
also i'm not sure you can open a conn after it has been closed. i think you have to make a new one.
Calling a stored procedure in a loop is not a good idea, I guess.
If it is MS SQL Server, use user-defined table type and table-valued parameter!
This allows you to call the stored procedure once.
How to Save Object Graph in Master-Detail Relationship with One Stored Procedure.
You should be using
cmd.ExecuteNonQuery();
Instead of
reader = cmd.ExecuteReader();
You are closing your connection after the first loop.
If you really want to go to DB every loop you have to open a new connection for each round.
Either way, I think you shouldn't hit the DB so many times. Have you think about BulkInsert?
Take a look here
I am posting a query first time here, So, Please ignore my formatting.
I am trying to update my .accdb file using update command, but result of oledbcommand.executeNonQuery() is 0 hence result is not updating in the database.
Though I am receiving no errors.
Here is what I am doing.
string vsql = string.Format("UPDATE DefTask_List SET [Action]=#Action WHERE [SNo]=#SNo");
vcom.Parameters.AddWithValue("#SNo", row.Cells[0].Value.ToString());
vcom.Parameters.AddWithValue("#Action", comboBox1.Text);
OleDbCommand vcom = new OleDbCommand(vsql, vcon);
vcon.Open();
int k = vcom.ExecuteNonQuery();
vcom.Dispose();
vcon.Close();
Please note that SNo is an autonumber in my .accdb file also with the same way I am inserting and deleting data but that is working fine.
OleDbCommand doesn't support named parameters. The only matter is their orders.
From OleDbCommand.Parameters property
The OLE DB .NET Provider does not support named parameters for passing
parameters...
Therefore, the order in which OleDbParameter objects are added to the
OleDbParameterCollection must directly correspond to the position of
the question mark placeholder for the parameter in the command text.
That's why your first #Action in OleDbCommand matches with #SNo in your AddWithValue and #SNo matches with your #Action in your AddWithValue.
Since probably you don't have a data like this, there will be no update operation.
Switch your parameter orders and use .Add method which is recommended instead of AddWithValue. It may generate unexpected results. Read;
Can we stop using AddWithValue() already?
Also use using statement to dispose your OleDbConnection and OleDbCommand instead of calling .Dispose() and .Close() methods manually.
using(OleDbConnection vcon = new OleDbConnection(conString))
using(OleDbCommand vcom = vcon.CreateCommand())
{
vcom.CommandText = "UPDATE DefTask_List SET [Action]=#Action WHERE [SNo]=#SNo";
vcom.Parameters.Add("?", OleDbType.VarChar).Value = comboBox1.Text;
vcom.Parameters.Add("?", OleDbType.Integer).Value = (int)row.Cells[0].Value;
// I assume your column types are NVarchar2 and Int32
vcon.Open();
int k = vcom.ExecuteNonQuery();
}
Hello so i m creating a registration form in C# with MySql so it connects to the database and everything but i get this error Napaka pri registraciji Unknown column " in 'field list' the translation of Napaka pri registraciji means Error at registering i just have it in my language. I get this error when i insert data in textboxes and press Register..
the code:
private void btn_Reg_Click(object sender, EventArgs e)
{
MySqlConnection dataConnection = new MySqlConnection();
dataConnection.ConnectionString = "datasource=localhost;port=3306;username=root;password=";
dataConnection.Open();
MySqlTransaction transakcija = dataConnection.BeginTransaction();
MySqlCommand dataCommand = new MySqlCommand();
dataCommand.Connection = dataConnection;
dataCommand.Transaction = transakcija;
try
{
dataCommand.CommandText = "Insert INTO lr.users (upIme,geslo) VALUES (`"+this.tB_upIme.Text+"`,`"+this.tB_geslo.Text+"`)";
dataCommand.CommandType = CommandType.Text;
dataCommand.ExecuteNonQuery();
transakcija.Commit();
MessageBox.Show("Registracija uspešna!");
}
catch (Exception eks)
{
transakcija.Rollback();
MessageBox.Show("Napaka pri registraciji\n" + eks.Message);
}
finally
{
dataCommand.Connection.Close();
}
}
There are two things I immediately see wrong here...
First, you're using back ticks to wrap your values. In MySQL Back ticks represent database objects, so the query is looking for objects named by those values instead of using the values themselves. So instead of this:
`"+this.tB_upIme.Text+"`
You'd want this:
'"+this.tB_upIme.Text+"'
Second, and vastly more importantly, your code is wide open to SQL injection attacks. You'll want to use query parameters, not direct string concatenation. While it may look like you're just putting values into the query string, you're actually taking user input and treating it as executable code in your query string, which means users can run any arbitrary code they want on your database.
First, add parameters to your query:
"Insert INTO lr.users (upIme,geslo) VALUES (#upIme, #geslo)"
(You'll notice this also makes the query a heck of a lot cleaner and easier to read.) Then add your parameters to the command:
dataCommand.Parameters.AddWithValue("#upIme", this.tB_upIme.Text);
dataCommand.Parameters.AddWithValue("#geslo", this.tB_geslo.Text);
Then when you execute that command it will treat the user-input values as values instead of as executable code.
Change to single quotes ' in the values.
dataCommand.CommandText =
"Insert INTO lr.users (upIme,geslo)
VALUES ('"+this.tB_upIme.Text+"','"+this.tB_geslo.Text+"');";
Why do I get an exception when trying to truncate a MySQL table (using MySQL Connector/Net)? I am trying to give the table name with a parameter.
This is the code I'm executing:
var connectionString = "Server="+_server+";Uid="+_user+";Pwd="+_password+";Database="+_database+";";
try
{
using (var conn = new MySqlConnection(connectionString))
{
conn.Open();
const string sql = "TRUNCATE TABLE #tablename"; // also tried with TRUNCATE #tablename
var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#tablename", "test");
cmd.ExecuteNonQuery();
conn.Close();
}
}
catch (MySqlException ex)
{
Console.WriteLine(ex.ToString());
}
And this is the execption:
MySql.Data.MySqlClient.MySqlException (0x80004005): You have an error
in your SQ L syntax; check the manual that corresponds to your MySQL
server version for the right syntax to use near ''test'' at line 1
When I try a select query, for example, then I don't have any problems. This runs fine and returns correct data:
conn.Open();
const string sql = "SELECT body FROM test WHERE id=#pid";
var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#pid", 1);
cmd.ExecuteScalar();
conn.Close();
Parameters are used for query values, not object names like tables.
So this will not work for sure.
You need to set the table name in the command string by using string concatenation. You can avoid sql injection attacks by manually checking for weird characters in the table name (spaces, dashes, semicolons, etc..)
I've been playing around with this for a while now, and i can't seem to get it to work either. I can't find any documentation online, so i'm starting to think you may not be able to truncate with a parameter like you've tried.
However, is there really a need to prevent SQL injection on this command? Does the user enter the name of the table they want to truncate, and if so, they're just going to truncate a table which...is essentially what the command does anyway?