changes to db from csharp are partly commited - c#

so as title says, I have a .net program that has a method( names dont matter )..
so theres a method where I loop through a datatable and fill it with data from csv, then i build a query where I add the parameters and do
insert into bakashot id,name,bla values(:id,:name,:bla);
and I build the parameters like this for example
cmd.Parameters[":id"].Value = id;
Anyways, all good, database table is filled with values.
Now, I have another table lets say bakashot_history, I want before that insert statement to the bakashot table, to take the records from original bakashot, insert them to the bakashot_history table, and then clean the records from the bakashot table.
I've noticed that it will only commit if I put a debug on, otherwise theres no exception or anything -it just wont commit.
so Im thinking like, if the insert statement went well without any need of debug or thread.sleep(which I tried aswell) , why do the DELETE statement and the "Transfer"(insert into a from b) suddenly needs the debug? thats wierd and im clueless..
any help will be appreciated!

nobody replied to my post,but eitherway the solution was wrapping everything with oracle transaction
using (OracleTransaction tran = myConnection.BeginTransaction())
{
StringBuilder sql = new StringBuilder("INSERT INTO Bakashot_Mll_TOCharge
(ID)" + "VALUES (:ID");
using (OracleCommand cmd = new OracleCommand(sql.ToString(), myConnection))
{
cmd.Transaction = tran;
AddTableParameters(cmd);
foreach (DataRow row in dt.Rows)
{
cmd.Parameters[":ID"].Value = row[0];
cmd.ExecuteNonQuery();
}
}
-----//this is the part that didnt work unless the debug mode was on\\------
using (OracleCommand com = new
OracleCommand("Store_And_Delete", myConnection))
{
com.Transaction = tran;
com.CommandType = CommandType.StoredProcedure;
com.ExecuteNonQuery();
}
tran.Commit();
myConnection.Close();
}

Related

SqlException : Incorrect syntax near '1'

I am currently trying to implement SQL into a project with Unity3D. So far, I was able to do "normal" UPDATE, ADD, DELETE, DROP, ALTER, INSERT".
Trying to go a step further, I am trying to insert prepared statements, using this link as a guide
Here is my code :
SqlConnection sqlConnection = new SqlConnection(Connection.connectionString)
sqlConnection.Open();
SqlCommand cmd = new SqlCommand(null, sqlConnection);
cmd.CommandText = "INSERT INTO IngredientTypes (Name) VALUES (#name)";
SqlParameter nameParam = new SqlParameter("#name", SqlDbType.Text, 155);
nameParam.Value = Name;
cmd.Parameters.Add(nameParam);
cmd.Prepare();
cmd.ExecuteNonQuery();
My table looks like so :
CREATE TABLE IngredientTypes
(
IngredientTypeID INT IDENTITY(1,1) PRIMARY KEY,
Name VARCHAR(155)
);
I get this error :
SQLException : Incorrect systax near '1'.
System.Data.SqlClient.SqlConnection.ErrorHandler (System.Object sender, Mono.Data.Tds. Protocol.TdsInternalErrorMessageEventArgs e)
Help please? Thank you in advance.. I can't find where I did wrong.
You can reduce that code quite a bit with no loss of function, and even some important improvements (for example, this will close the connection even if an exception is thrown):
using (var sqlConnection = new SqlConnection(Connection.connectionString))
using (var cmd = new SqlCommand("INSERT INTO IngredientTypes (Name) VALUES (#name)", sqlConnection))
{
cmd.Parameters.Add("#name", SqlDbType.VarChar, 155).Value = Name;
sqlConnection.Open();
cmd.ExecuteNonQuery();
}
I'm not sure what's causing that exception in your existing code, though, because 1 is not used anywhere in that query. I suspect the problem has something to do with SqlDbType.Text, since that is not the correct type to use with a VarChar column, but it seems just as likely there's code somewhere we haven't seen yet that's changing your SQL command text.
Definitely the Prepare() method in your link is not needed for Sql Server. It's inherited here from DbCommand, where it's included because it's an important part of the API for some other databases, but Sql Server has handled this automatically for more than 10 years now.
SqlDbType.Text Is not the same as varchar. I don’t believe Text types have a length you specify.
Could you try below? Using the "using" structure is safer for sql connections by the way, the connection automatically closes when your process is done.
using (SqlConnection sqlConnection = new SqlConnection(Connection.connectionString))
{
SqlCommand command = new SqlCommand("INSERT INTO IngredientTypes (Name) VALUES (#name)", connection);
command.Parameters.Add("#name", SqlDbType.Varchar, 155);
command.Parameters["#name"].Value = Name; //make sure Name is string.
try
{
sqlConnection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I tried your code exactly as it is and found no issue. Though there are few compilation errors (missing ; in line 1 and Name variable should be coming as parameter) but I am sure you know that. If you have posted your table structure and code exactly the same as you have in your project, then there is no problem in this code.

For loop only writing to my mssql stored procedure once?

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

C# Sql Command for Insering into a database

I am new to Visual C# programming language and recently i was trying to make a application that is supposed to insert into a local database of users some data but every times my code runs and the insertion works fine the database does not update.This is the code that i am using
try
{
cn.Open();
SqlCommand insert = new SqlCommand();
insert.CommandText = "insert into Clienti (Nume,Prenume,Parola,Email) values(#Nume,#Prenume,#Parola,#Email)";
insert.Connection = cn;
insert.Parameters.AddWithValue("#Nume", register_nume.Text);
insert.Parameters.AddWithValue("#Prenume", register_prenume.Text);
insert.Parameters.AddWithValue("#Parola", register_password.Text);
insert.Parameters.AddWithValue("#Email", register_email.Text);
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
MessageBox.Show("Added succesfully");
}
catch (Exception ex)
{
MessageBox.Show(""+ex);
}
I already tried the property Copy to output and it doesn't seems to work.
I am sorry for any grammar mistakes that i made,I would be grateful for any help.
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
You only need the ExecuteNonQuery, it will run the INSERT. You need to use ExecuteReader instead only when you're running a statement that produces result sets (eg. SELECT). So it should be:
insert.ExecuteNonQuery();
Its because you have to now read the database using a select statement, you cant use an INSERT SQL statement to read.
You could add the following immediately after your insert.
using(var selectCmd = new SqlCommand("SELECT Nume,Prenume,Parola,Email FROM Clienti WHERE Nume = #Nume", cn))
{
selectCmd.Parameters.AddWithValue("#Nume", register_nume.Text);
using(SqlDataReader reader = selectCmd.ExecuteReader())
{
while (reader.Read()) { }
}
}
That said if you want to know IF the row was inserted or how many records were inserted ExecuteNonQuery returns the number of rows affected. You could change that part of the code like this:
var recordsAffected = insert.ExecuteNonQuery();
if(recordsAffected > 0)
MessageBox.Show("Added succesfully");
else
MessageBox.Show("Nothing happened");
Although in this particular case it would not make sense because if nothing was inserted it would probably be caused by an Exception.
Some side notes
Always wrap types that implement IDisposable in using blocks (see code above as example). It ensures that resources are always released as soon as you are done with them even if an Exception is thrown.
Never swallow Exceptions! Either recover from one and log it or do not catch it at all. If you swallow it you will never know if/why your code broke.
This part of your code is preparing the SQL command that you are running
cn.Open();
SqlCommand insert = new SqlCommand();
insert.CommandText = "insert into Clienti (Nume,Prenume,Parola,Email) values(#Nume,#Prenume,#Parola,#Email)";
insert.Connection = cn;
insert.Parameters.AddWithValue("#Nume", register_nume.Text);
insert.Parameters.AddWithValue("#Prenume", register_prenume.Text);
insert.Parameters.AddWithValue("#Parola", register_password.Text);
insert.Parameters.AddWithValue("#Email", register_email.Text);
The SQL command that your code is running, is an INSERT statement, which only adds a new record to your table.
This statement runs the command that you setup earlier:
insert.ExecuteNonQuery();
If I understand correctly, here you are trying to read the data from the table again:
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
Problem is, your command is NOT set for reading. To read data, you need to use a SELECT statement. Something like this:
insert.CommandText = "SELECT Nume,Prenume,Parola,Email from Clienti" ;
So, to read the data after executing the insert, you should do this:
insert.CommandText = "SELECT Nume,Prenume,Parola,Email from Clienti" ;
SqlDataReader reader = insert.ExecuteReader();
while (reader.Read()) { }
You ar executing 2 times the query:
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
Try to get the affected rows
int rows = insert.ExecuteNonQuery();
I would suggest creating a stored procedure in your database and just execute the SP.
It's always better to execute SP from code and leave the SQL programming in the DB.

INSERT INTO c# to Microsoft access

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.

How to update a large table using ADO.NET

Ok, so here's the problem I have to solve. I need to write a method in C# that will modify a table in SQL Server 2008. The table could potentially contain millions of records. The modifications include altering the table by adding a new column and then calculating and setting the value of the new field for every row in the table.
Adding the column is not a problem. It's setting the values efficiently that is the issue. I don't want to read in the whole table into a DataTable and then update and commit for obvious reasons. I'm thinking that I would like to use a cursor to iterate over the rows in the table and update them one by one. I haven't done a whole lot of ADO.NET development, but it is my understanding that only read-only server side (firehose) cursors are supported.
So what is the correct way to go about doing something like this (preferably with some sample code in C#)? Stored procedures or other such modifications to the DB are not allowed.
jpgoody,
Here is an example to chew on using the NerdDinner database and some SQLConnection, SQLCommand, and SQLDataReader objects. It adds one day to each of the Event Dates in the Dinners table.
using System;
using System.Data.SqlClient;
namespace NerdDinner
{
public class Class1
{
public void Execute()
{
SqlConnection readerConnection = new SqlConnection(Properties.Settings.Default.ConnectionString);
readerConnection.Open();
SqlCommand cmd = new SqlCommand("SELECT DinnerID, EventDate FROM Dinners", readerConnection);
SqlDataReader reader = cmd.ExecuteReader();
SqlConnection writerConnection = new SqlConnection(Properties.Settings.Default.ConnectionString);
writerConnection.Open();
SqlCommand writerCommand = new SqlCommand("", writerConnection);
while (reader.Read())
{
int DinnerID = reader.GetInt32(0);
DateTime EventDate = reader.GetDateTime(1);
writerCommand.CommandText = "UPDATE Dinners SET EventDate = '" + EventDate.AddDays(1).ToString() + "' WHERE DinnerID = " + DinnerID.ToString();
writerCommand.ExecuteNonQuery();
}
}
}
}
Your problem looks like something that you should be solving using T-SQL and not C#, unless there is some business rule that you are picking up dynamically and calculating the column values T-SQL should be the way to go. Just write a stored procedure or just open up Management studio and write the code to make your changes.
If this does not help then please elaborate on what exactly you want to do to the table, then we can help you figure out if this can be done via T-SQL or not.
[EDIT] you can do something like this
string sql = " USE " + paramDbName;
sql+= " ALTER TABLE XYZ ADD COLUMN " + param1 + " datatype etc, then put semicolon to separate the commands as well"
sql+= " UPDATE XYZ SET Columnx = " + some logic here
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
get this executed on the required instance of Sql Server 2008.
If you have too many lines of text then use StringBuilder.
Here's a suggestion:
You can read data using a DataReader , create a update command for current row and add it to a list of commands.Then run update commands in a transaction.
something like this:
var commands=new List<SqlCommand>();
while(dr.Read())
{
var cmd=new SqlCommand();
cmd.CommandText="Add your command text here";
commands.Add(cmd);
}
using(var cnn=new SqlConnection("Connection String"))
{
IDbTransaction transaction;
try
{
cnn.Open();
transaction=cnn.BeginTransaction();
foreach(var cmd in commands)
{
cmd.Transaction=transaction;
cmd.ExecuteNonQuery();
cmd.Dispose();
}
transaction.Commit();
}
catch(SqlException)
{
if(transaction!=null)
transaction.Rollback();
throw;
}
}

Categories