I am executing UPDATE OR INSERT command with WHERE statement and I've got this error:
Here is my code:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
FbConnection con = new FbConnection(#"User = SYSDBA; Password = masterkey; Database = D:\TDWORK.fdb; DataSource = localhost; Port = 3050; Dialect = 3; Charset = NONE; Role = admin; Connection lifetime = 15; Pooling = true; MinPoolSize = 0; MaxPoolSize = 50; Packet Size = 8192; ServerType = 0; ");
FbCommand cmd = new FbCommand("UPDATE OR INSERT INTO ZAPOSLENI (ULOGA) VALUES (" + dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() + ") WHERE ZAPID = " + dataGridView1.Rows[e.RowIndex].Cells[0].Value + " ", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
And here is how command looks like when debugger insert values in it:
UPDATE OR INSERT INTO ZAPOSLENI (ULOGA) VALUES (1) WHERE ZAPID = 0
You cannot use WHERE in an insert or update clause (see UPDATE OR INSERT). If you want to insert a row, when there is no record with ZAPID = 0 use the following statement:
UPDATE OR INSERT INTO ZAPOSLENI (ZAPID, ULOGA) VALUES (0, 1) MATCHING (ZAPID)
EDIT: Complete example
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
FbConnection con = new FbConnection(#"User = SYSDBA; Password = masterkey; Database = D:\TDWORK.fdb; DataSource = localhost; Port = 3050; Dialect = 3; Charset = NONE; Role = admin; Connection lifetime = 15; Pooling = true; MinPoolSize = 0; MaxPoolSize = 50; Packet Size = 8192; ServerType = 0; ");
FbCommand cmd = new FbCommand("UPDATE OR INSERT INTO ZAPOSLENI (ZAPID, ULOGA) VALUES (" + dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() + ", " + dataGridView1.Rows[e.RowIndex].Cells[0].Value + ") MATCHING (ZAPID)", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Related
I'm new here but I need some help. I need to update a SQL Server database from C# with Windows Forms, but I'm having problems. I looked it up but still can't find the right answer. I need to do insert and update by pressing a button for changing or filling the database from the datagridview. I've created a separate function for both I am using this code;
private void InsertPositionen()
{
string qry = "";
SqlCommand insert = new SqlCommand(qry, con);
try
{
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
qry = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) VALUES( " + dataGridView1.Rows[i].Cells["BelID"] + ", "
+ dataGridView1.Rows[i].Cells["BelPosId"] + ", "
+ dataGridView1.Rows[i].Cells["Artikelnummer"] + ", "
+ dataGridView1.Rows[i].Cells["Menge"] + ", "
+ dataGridView1.Rows[i].Cells["Preis"];
}
insert.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void UpdatePositionen()
{
string updt = "";
SqlCommand update = new SqlCommand(updt, con);
try
{
for (int i = 0; i < dataGridView1.Rows.Count -1; i++)
{
updt = "UPDATE BelegePositionen SET BelID = "
+ dataGridView1.Rows[i].Cells["BelID"] +
", BelPosID = "
+ dataGridView1.Rows[i].Cells["BelPosID"] +
", Atrikelnummer = "
+ dataGridView1.Rows[i].Cells["Artikelnummer"] +
", Menge = "
+ dataGridView1.Rows[i].Cells["Menge"] +
", Preis = "
+ dataGridView1.Rows[i].Cells["Preis"];
}
update.ExecuteNonQuery();
con.Close();
MessageBox.Show("Done!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You should really NOT do your SQL stuff like this!! This leaves your code wide open for SQL injection vulnerabilities! Stop that - right now!
Instead - use parametrized queries - like this:
private void InsertPositionen()
{
string qry = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) " +
"VALUES(#BelId, #BelPosId, #ArtNr, #Menge, #Preis);";
SqlCommand insert = new SqlCommand(qry, con);
// define the parameters
insert.Parameters.Add("#BelId", SqlDbType.Int);
insert.Parameters.Add("#BelPosId", SqlDbType.Int);
insert.Parameters.Add("#ArtNr", SqlDbType.Int); // maybe this is a string?
insert.Parameters.Add("#Menge", SqlDbType.Int);
insert.Parameters.Add("#Preis", SqlDbType.Decimal, 20, 4);
try
{
// in the loop, only *set* the parameter's values
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
insert.Parameters["#BelId"].Value = 1;
insert.Parameters["#BelPosId"].Value = 2;
insert.Parameters["#ArtNr"].Value = 3;
insert.Parameters["#Menge"].Value = 4;
insert.Parameters["#Preis"].Value = 99.95;
insert.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Your Question is quite vague as you state you are having problems, but not quite sure what problems you are having. It will help if you can describe what problems you are having.
In addition to what #marc_c said about sql injection, I can't see how you manage your connection to the database.
From the code it looks like you could run into a situation where you are leaving connection strings open, or not opening them at all.
using the using(...) { } will close the connections when you are done with it.
private void InsertPositionen()
{
//using the using statement you will insure that the connection is closed and resources released
using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.db))
{
string cmd = "INSERT INTO BelegePositionen (BelID, BelPosId, Artikelnummer, Menge, Preis) " +
"VALUES(#BelId, #BelPosId, #ArtNr, #Menge, #Preis);";
//using the using statement will ensure any reasources are released when exiting the code block
using (SqlCommand insert = new SqlCommand(cmd, connection))
{
// define the parameters
insert.Parameters.Add("#BelId", SqlDbType.Int);
insert.Parameters.Add("#BelPosId", SqlDbType.Int);
insert.Parameters.Add("#ArtNr", SqlDbType.Int); // maybe this is a string?
insert.Parameters.Add("#Menge", SqlDbType.Int);
insert.Parameters.Add("#Preis", SqlDbType.Decimal, 20, "4");
try
{
//open the connection
insert.Connection.Open();
// in the loop, only *set* the parameter's values
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
insert.Parameters["#BelId"].Value = dataGridView1.Rows[i].Cells["BelID"];
insert.Parameters["#BelPosId"].Value = dataGridView1.Rows[i].Cells["BelPosId"];
insert.Parameters["#ArtNr"].Value = dataGridView1.Rows[i].Cells["Artikelnummer"];
insert.Parameters["#Menge"].Value = dataGridView1.Rows[i].Cells["Menge"];
insert.Parameters["#Preis"].Value = dataGridView1.Rows[i].Cells["Preis"];
insert.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
MessageBox.Show("Done!");
}
}
}
}
I'm working on an app with an Access 2010 db connection and I keep receiving OleDB error 80004005 and I can't figure out why.
const String conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\OneDrive\Dropbox\SharpDevelop Projects\electronics inventory\electronics.mdb";
const String qCont = "select Section, Number, Stock from Container where Component = #IdComp order by Section, Number";
int oldParamSubcat = 0;
OleDbConnection connection = new OleDbConnection(conn);
void GrdCompCellClick(object sender, DataGridViewCellEventArgs e)
{
String IdComp = grdComp[grdComp.Columns["ID"].Index, grdComp.CurrentCell.RowIndex].Value.ToString();
try
{
grdSubcat.DataSource = null;
grdSubcat.Rows.Clear();
grdSubcat.Columns.Clear();
connection.Open();
OleDbCommand cmdDetail = new OleDbCommand();
cmdDetail.Connection = connection;
cmdDetail.CommandText = qDetail;
cmdDetail.Parameters.AddWithValue("#IdComp", Convert.ToInt32(IdComp));
txtDetails.Text = "";
OleDbDataReader rdDetail = cmdDetail.ExecuteReader();
rdDetail.Read();
txtDetails.Text = rdDetail["Component"].ToString() + "\r\n";
txtDetails.Text += rdDetail["Parameter"].ToString() + ": ";
txtDetails.Text += rdDetail["Val"].ToString() + "\r\n";
while(rdDetail.Read())
{
txtDetails.Text += rdDetail["Parameter"].ToString() + ": ";
txtDetails.Text += rdDetail["Val"].ToString() + "\r\n";
}
rdDetail.Close();
connection.Close();
connection.Open();
OleDbCommand cmdCode = new OleDbCommand();
cmdCode.Connection = connection;
cmdCode.CommandText = qCode;
cmdCode.Parameters.AddWithValue("#IdComp", Convert.ToInt32(IdComp));
txtDetails.Text += "\r\n";
OleDbDataReader rdCode = cmdCode.ExecuteReader();
while(rdCode.Read())
{
txtDetails.Text += rdCode["Seller"].ToString() + ": ";
txtDetails.Text += rdCode["Code"].ToString() + "\r\n";
}
rdCode.Close();
connection.Close();
connection.Open();
OleDbCommand cmdCont = new OleDbCommand();
cmdCont.Connection = connection;
cmdCont.CommandText = qCont;
cmdCont.Parameters.AddWithValue("#IdComp", Convert.ToInt32(IdComp));
txtDetails.Text += "\r\n";
OleDbDataReader rdCont = cmdCont.ExecuteReader(); ////////// here is where i receive the error ///////////////
while(rdCont.Read())
{
txtDetails.Text += "Container: ";
txtDetails.Text += rdCont["Section"].ToString() + "-";
txtDetails.Text += rdCont["Number"].ToString() + " = ";
txtDetails.Text += rdCont["Stock"].ToString() + " units\r\n";
}
rdCont.Close();
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
The rest of the code works perfectly, I only get the error on cmdCont.ExecuteReader();
The error message
If i execute the query in Access, it runs ok.
Any ideas are very much welcome.
Thanks.
The words Section, Number and Container are listed between the reserved keyword for MS-Access. You shouldn't use them in your table schema but if you really can't change these names to something different then you need to put them between square brackets
const String qCont = #"select [Section], [Number], Stock from [Container]
where Component = #IdComp order by [Section], [Number]";
Also you should use a more robust approach to your disposable objects like the connection, the commands and the readers. Try to add the using statement to your code in this way:
try
{
....
using(OleDbConnection connection = new OleDbConnection(......))
{
connection.Open();
....
string cmdText = "yourdetailquery";
using(OleDbCommand cmdDetail = new OleDbCommand(cmdText, connection))
{
.... // parameters
using(OleDbDataReader rdDetail = cmdDetail.ExecuteReader())
{
... read detail data ....
}
}
// here the rdDetail is closed and disposed,
// you can start a new reader without closing the connection
cmdText = "yourcodequery";
using(OleDbCommand cmdCode = new OleDbCommand(cmdText, connection))
{
.... parameters
using(OleDbReader rdCode = cmdCode.ExecuteReader())
{
// read code data...
}
}
... other command+reader
}
// Here the connection is closed and disposed
}
catch(Exception ex)
{
// any error goes here with the connection closed
}
I try to updata a single row, chosen by it ID. But what I got at best is an additional row instead of an updated one.
I made several attempts. Now I got a System.InvalidOperationException claiming that a valid InsertCommand is necessary for an update, if a DataRow listing will get a new row.
To me it is the same again: Why insert? I want to update.
Can anybody give me a hint?
This is my related code:
string selectQuery = $"SELECT * FROM Records";
string updateQuery = $"UPDATE Records SET AnyContent = #AnyContent WHERE [ID] = #ID";
OleDbDataAdapter adapter = null;
OleDbCommand cmd = null;
try
{
adapter = new OleDbDataAdapter(selectQuery, ConnectionString);
cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = updateQuery;
cmd.Parameters.AddWithValue ("#AnyContent", "066066");
cmd.Parameters.AddWithValue("#ID", 2);
try
{
adapter.UpdateCommand = cmd;
nbRowsChanged = adapter.Update(content);
}
finally
{
adapter?.Close();
cmd?.Close();
}
}
catch (OleDbException e)
{
logText += "...Database Exception:\n\n" + e.Message + "\n\n";
isSuccess = false;
}
if (0 < nbRowsChanged)
{
logText += ".... Success: Updated <" + nbRowsChanged.ToString() + "> rows.\n";
isSuccess = true;
}
<<< Update >>>
Originally I tried it with an OleDbCommandBuilder before. But CommandBuilder created an update command, which seems to me like an insert command. This is why I tried it without CommandBuilder above. But inserting seems to follow me.
This is my old code, which is closer to where I want to get as it uses a DataTable instead of parameters:
string selectQuery = $"SELECT * FROM Records WHERE [ID] = ?";
OleDbConnection con = null;
OleDbDataAdapter adapter = null;
OleDbCommandBuilder builder = null;
try
{
adapter = new OleDbDataAdapter();
con = new OleDbConnection(ConnectionString);
adapter.SelectCommand = new OleDbCommand(selectQuery, con);
builder = new OleDbCommandBuilder(adapter);
try
{
con.Open();
nbRowsChanged = adapter.Update(content);
logText += "....InsertCommand: " + builder.GetInsertCommand().CommandText + "\n"; // Just to debug
logText += "....UpdateCommand: " + builder.GetUpdateCommand().CommandText + "\n"; // Just to debug
}
finally
{
con?.Close();
adapter?.Dispose();
}
}
catch (OleDbException e)
{
logText += "...Database Exception:\n\n" + e.Message + "\n\n";
isSuccess = false;
}
if (0 < nbRowsChanged)
{
logText += ".... Success: Updated <" + nbRowsChanged.ToString() + "> rows.\n";
isSuccess = true;
}
logText += tmpText ;
logText += "...Database: Access disposed.\n";
return isSuccess;
And this is the related trace:
LogText:
...Database: Trying to update <1> number of rows in table <Records>
....InsertCommand: INSERT INTO Records (AnyContent) VALUES (?)
....UpdateCommand: UPDATE Records SET AnyContent = ? WHERE ((ID = ?) AND ((? = 1 AND AnyContent IS NULL) OR (AnyContent = ?)))
.... Success: Updated <1> rows.
...Database: Access disposed.
NbRows Before: 5
NbRows After: 6
I have a datagridview which is created by various action and user's manipulation of data. I want to insert all the data of the gridview to the database at once, I know I could try a code similar to this:
private void btnSaveProducts_Click(object sender, EventArgs e)
{
SqlConnection connection = DBConnectivity.getConnection();
if (connection != null)
{
try
{
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
string query = "INSERT INTO product (productName) " + "VALUES (#productName)";
SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
int result = command.ExecuteNonQuery();
Console.WriteLine(result + "");
}
// string query = "Insert into units(name,packing)values('" + txtNameUnit.Text + "' , '" + txtPackingUnit.Text + "')";
// SqlCommand command = DBConnectivity.getCommandForQuery(query, connection);
// int result = command.ExecuteNonQuery();
// Console.WriteLine(result + "");
}
catch (Exception ex)
{
}
finally
{
connection.Close();
}
}
}
As is, the code tries to execute a parameterized query but never assigns a value to the parameter. Even if you do, you never extract the cell values.
The code should look like this:
var query = "INSERT INTO product (productName) VALUES (#productName)";
using var(connection = DBConnectivity.getConnection())
using(var command = new SqlCommand(query, connection))
{
var productParam=command.Parameters.Add("#productName",SqlDbType.NVarChar,50);
connection.Open();
for (int i = 0; i < dGvProducts.Rows.Count; i++)
{
var productName=dGvProducts.Rows[i].Cells[somecolumn].Value;
productParam.Value=productName;
int result = command.ExecuteNonQuery();
Console.WriteLine(result);
}
}
protected override void OnStart(string[] args)
{
try
{
t.Enabled = true;
t.Interval = 10000; //60 * 24;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
}
catch (Exception ex)
{
writeErrorToFile(ex.Message + " -- (OnStart) --");
}
}
this is my onstart method. I am new to making the windows service. Can you explain me what the code inside the instart method does.? I am not able to get the right answer when i googled.
Following is the method that is called from the onstart method
private void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
// Read Data from Excel
OleDbConnection conn = new OleDbConnection();
OleDbCommand cmd = new OleDbCommand();
OleDbDataAdapter da = new OleDbDataAdapter();
SqlCommand sm = new SqlCommand();
string connString = "";
string query = "";
string strDt = DateTime.Now.ToString("dd_MM_yyyy");
string strNewPath = #"E:\E-Cata_Stock_Report\ALL_INDIA_STOCK_REPORT_" + strDt + ".xls"; //Server.MapPath(#"C:\E-Cata_Stock_Report\ALL_INDIA_STOCK_REPORT.xls"); // ///" + strFileName + strFileType);
connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strNewPath +
";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
query = "SELECT * FROM [SPARE_LIST$]";
conn = new OleDbConnection(connString);
//Open connection
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Open();
//Create the command object
cmd = new OleDbCommand(query, conn);
da = new OleDbDataAdapter(cmd);
dsExcel = new DataSet();
try
{
da.Fill(dsExcel);
}
catch (Exception ex)
{
writeErrorToFile(ex.Message + " -- (t_Elapsed -> Keep valid excel file which you want to upload..) --");
//lblMsg.Text = "Keep valid excel file which you want to upload..";
return;
}
//lblMsg.Text = "Data retrieved successfully! Total Records:" + dsExcel.Tables[0].Rows.Count;
da.Dispose();
conn.Close();
conn.Dispose();
if (dsExcel.Tables[0].Columns.Count != 32)
{
writeErrorToFile("Please check the Excel Sheet.. It contains more or less columns..");
return;
}
if (dsExcel.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < dsExcel.Tables[0].Rows.Count; i++)
File.AppendAllText(#"C:\E-Cata_Itms.txt", dsExcel.Tables[0].Rows[i][0].ToString() + " \n\r"+i+i);
}
//======================================================================================================
string con = getConn_string();
SqlConnection sn = new SqlConnection(con);
if (sn.State == ConnectionState.Open)
sn.Close();
sn.Open();
SqlTransaction transaction = sn.BeginTransaction();
try
{
for (int j = 4; j < dsExcel.Tables[0].Rows.Count; j++) // for rows
{
for (int i = 2; i < 32; i++) //for coloumns
{
sm = new SqlCommand();
sm.Transaction = transaction;
sm.CommandText = "whItmItemwise_upload_update";
sm.Connection = sn;
sm.CommandType = CommandType.StoredProcedure;
sm.Parameters.AddWithValue("#whItm_wh_code", dsExcel.Tables[0].Rows[3][i].ToString().Trim());
sm.Parameters.AddWithValue("#whItm_item_code", dsExcel.Tables[0].Rows[j][0].ToString().Trim());
try
{
// open stock quantity
decimal op_qty = (dsExcel.Tables[0].Rows[j][i].ToString().Trim() ==
"")
? Convert.ToDecimal(0.0)
: Convert.ToDecimal(
dsExcel.Tables[0].Rows[j][i].ToString().Trim
());
sm.Parameters.AddWithValue("#whItm_OP_STK_Qty", op_qty);
}
catch (Exception ex)
{
writeErrorToFile(ex.Message + " -- (t_Elapsed -> Enter valid Open stock quantity..) --"+i);
return;
}
sm.Parameters.AddWithValue("#whItm_Creation_DT", DateTime.Now.ToString("yyyy/MM/dd"));
//sm.Parameters.AddWithValue("#whItm_Created_By", "");
//sm.Parameters.AddWithValue("#His_whItm_Modify_Del_DT", DateTime.Now.ToString("yyyy/MM/dd"));
//sm.Parameters.AddWithValue("#His_whItm_Modify_Del_By", "");
try
{
int x = sm.ExecuteNonQuery();
}
catch (Exception ex)
{
System.Text.StringBuilder str_Upload = new System.Text.StringBuilder();
str_Upload.Append(dsExcel.Tables[0].Rows[3][i].ToString().Trim() + ",");
str_Upload.Append(dsExcel.Tables[0].Rows[j][0].ToString().Trim() + ",");
str_Upload.Append(ex.Message.Replace(',', '-') + ",");
str_Upload.Append(DateTime.Now.ToString("dd/MM/yyyy") + ",");
File.AppendAllText(#"C:\E-Cata_Error" + ".csv", str_Upload.ToString());
}
sm.Parameters.Clear();
}
}
// Update stock from WH master to Item Master
SqlCommand sm2 = new SqlCommand();
sm2.Transaction = transaction;
sm2.CommandText = "Stock_Update_from_WH_to_Item_master";
sm2.Connection = sn;
sm2.CommandType = CommandType.StoredProcedure;
sm2.Parameters.AddWithValue("#Item_Code", "");
sm2.ExecuteNonQuery();
transaction.Commit();
sm2.Dispose();
MyNewService iyu = new MyNewService();
iyu.Stop();
}
catch (Exception ex)
{
transaction.Rollback();
writeErrorToFile(ex.Message+"abcd");
return;
}
finally
{
sm.Dispose();
transaction.Dispose();
sn.Close();
sn.Dispose();
}
//try
//{
// // delete uploaded file
// File.Delete(strNewPath);
//}
//catch (Exception)
//{
//}
}
catch (Exception ex)
{
writeErrorToFile(ex.Message + " -- (t_Elapsed) --"+"xyz");
}
}
Windows service has to inherit from ServiceBase class. It has OnStart and OnStop virtual methods that we need to override in the service class.
In your code, when the windows service is started, OnStart method is invoked. In this method the timer is enabled and set the interval to 10 sec. Timer interval always sets in milliseconds, that’s why value is 10000. When 10 sec elapsed the method subscribed in the Elapsed event is fired, in this case the t_Elapsed method in fired.
See the following article for hosting the wcf service in a managed windows service.
http://msdn.microsoft.com/en-us/library/ms733069.aspx