OleDb Update requires Insert Command? - c#

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

Related

How to check if user in mysql database exists (in c#)

So I know this is a often asked question but I want to check if the username is already taken in the database using c#. I tried this:
MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM tablename WHERE(name = '" + tb1.Text + "');");
cmd2.Connection = connect;
connect.Open();
string unt = "";
try
{
MySqlDataReader dr;
dr = cmd.ExecuteReader();
while (dr.Read())
{
unt= dr.GetString("name");
}
dr.Close();
}
catch (Exception ex)
{
errorbox.Content = ex.Message;
}
finally
{
connect.Close();
}
if(unt == "" || unt == "0") {
continuel = false;
tb2.Text = "User " +tb1.Text+ " doesn't exist!";
Popup1.IsOpen = true;
}
Its a WPF project and the variable 'continuel' is set to true by default. The code doesn't recognize if a user doesn't exist.
First off your code is vulnerable to sql inject, you should never concatenate values into a query. secondly you can do a count and execute a scalar. Not I stripped down your code a little you'll have to add error handling back.
bool userExists = false;
private String sql = "SELECT COUNT(*) FROM tableName WHERE name = #usernameparam;";
MySqlCommand m = new MySqlCommand(sql);
m.Parameters.AddWithValue("#usernameparam", tb1.Text.Trim());
int userCount = Convert.ToInt32(m.ExecuteScalar());
if(userCount>0)
{
userExists = true;
}
//use userExists variable to evaluate if user exists

c# Access OleDB err 80004005

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
}

Update query not throwing error

Thanks for the help in advance.
Im trying to use update query in C#
Error : command is getting executed even if I use incorrect values
Design view
Code :
protected void Button1_Click(object sender, EventArgs e)
{
try
{
con.Open();
cmd = new SqlCommand("update Comcast_AvayaID set Status='Inactive' where Employee_Id='" + TxtEMPID.Text + "' and AvayaID ='" + TxtAvayaID.Text + "'", con);
cmd = new SqlCommand("UPDATE Avaya_Id SET Status = 'UnAssigned' where Avaya_ID ='" + TxtAvayaID.Text + "'", con);
cmd.ExecuteNonQuery();
LBLSuccess.Visible = true;
LBLSuccess.Text = "Deactivation Successfull";
con.Close();
}
catch (SqlException ex)
{
LBLSuccess.Visible = true;
LBLSuccess.Text = "Deactivation Unsuccessfull";
}
your code would look better like this, it not the most optimal, but ia already a way better piece of code then your snippet
1) added parameters using a helper function for the sql injection issue
2) an ExecuteNonQuery returns the rows affected, so if you are expecting that 1 row was updated, you can check on that
3) if you update a row with an id that not exists, it will not throw a SqlException like you are expecting in your code, this happens e.g. when locking occurs
public void Update()
{
var con = new SqlConnection();
try
{
var empId = TxtEMPID.Text
var avayaId = TxtAvayaID.Text
con.Open();
var cmd1 = new SqlCommand("update Comcast_AvayaID set Status='Inactive' where Employee_Id=#empId and AvayaID = #avayaId", con);
cmd1.Parameters.Add(AddParameter("#empId",empId));
cmd1.Parameters.Add(AddParameter("#avayaId", avayaId));
var cmd2 = new SqlCommand("UPDATE Avaya_Id SET Status = 'UnAssigned' where Avaya_ID =avayaId", con);
cmd2.Parameters.Add(AddParameter("#avayaId", avayaId));
var rowsaffected1 = cmd1.ExecuteNonQuery();
var rowsAffected2 = cmd2.ExecuteNonQuery();
if (rowsaffected1 == 1 && rowsAffected2 == 1)
{
//success code goes here
//--------
LBLSuccess.Visible = true;
LBLSuccess.Text = "Deactivation Successfull";
}
else
{
// failure code goes here
//-----------------------
LBLSuccess.Visible = true;
LBLSuccess.Text = "Deactivation Unsuccessfull";
}
}
catch (SqlException ex)
{
//handle errors
}
finally
{
con.Close();
}
Console.ReadLine();
}
private SqlParameter AddParameter(string name, object value) {
var par = new SqlParameter();
par.ParameterName = name;
par.Value = value;
return par;
}
If you put "incorrect" values it just updates zero of records. No errors/exception expected here.

using one button to insert and update different db tables

I am using the same button "Save" to update a table called AnalysisExperiments and also to insert data into a table called "Analysis". however the update is not working. Here is the code:
#region Insert Data into Analysis Table
if (checkIfRepeatedJobNumber(tbJobNumber.Text.Trim()))
{
MessageBox.Show("Job Number is already exist.", "Repeated Data");
return;
}
string query = "insert into Analysis (ID, WellName, EstimatedStartDate, SOWComments, ProgressComments, Field, FocalPoint, StudyCompleted, Company, ReservoirPressure, ReservoirTemp, SelectedSamples) " +
"values (#ID, #WellName, #SamplingDate, #SOWComments, #ProgressComments, #Field, #FocalPoint, #StudyCompleted, #Company, #ReservoirPressure, #ReservoirTemp, #SelectedSamples)";
OleDbCommand cmd = new OleDbCommand(query, conn);
cmd.Parameters.AddWithValue("#ID", tbJobNumber.Text);
cmd.Parameters.AddWithValue("#WellName", tbWellName.Text);
cmd.Parameters.AddWithValue("#SamplingDate", dtpSamplingDate.Text);
cmd.Parameters.AddWithValue("#SOWComments", tbSOW_Comments.Text);
cmd.Parameters.AddWithValue("#ProgressComments", tbProgressComments.Text);
cmd.Parameters.AddWithValue("#Field", tbFieldName.Text);
cmd.Parameters.AddWithValue("#FocalPoint", tbFocalName.Text);
if (radYes.Checked)
cmd.Parameters.AddWithValue("#StudyCompleted", "Yes");
else
cmd.Parameters.AddWithValue("#StudyCompleted", "No");
cmd.Parameters.AddWithValue("#Company", tbCompany.Text);
cmd.Parameters.AddWithValue("#ReservoirPressure", tbReservoirPressure.Text);
cmd.Parameters.AddWithValue("#ReservoirTemp", tbReservoirTemp.Text);
cmd.Parameters.AddWithValue("##SelectedSamples", tbSelectedSamples.Text);
try
{
conn.Open();
int j = cmd.ExecuteNonQuery();
if (j == 1)
{
MessageBox.Show("Done");
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
}
#endregion
#region update analysis Exp but still no working
#region Update database
try
{ int k = 0;
OleDbDataAdapter da;
da = new OleDbDataAdapter("select* from [AnalysisExperiments]", conn);
string ExpQuery = "update AnalysisExperiments set SampleNumber = #SampleNumber, Status = #Status where ID = '" + tbJobNumber.Text + "' and Experiment = '";
foreach (DataGridViewRow row in dgvExperiments.Rows)
{
ExpQuery += row.Cells["Experiment"].Value.ToString() + "'";
OleDbCommand updateCommand = new OleDbCommand(ExpQuery, conn);
updateCommand.Parameters.Add("#SampleNumber", OleDbType.VarWChar);
MessageBox.Show(row.Cells["SampleNumber"].Value.ToString() + " | " + row.Cells["Status"].Value.ToString() + " | " + row.Cells["Experiment"].Value.ToString());
updateCommand.Parameters["#SampleNumber"].Value = row.Cells["SampleNumber"].Value.ToString();
updateCommand.Parameters.Add("#Status", OleDbType.Boolean);
updateCommand.Parameters["#Status"].Value = row.Cells["Status"].Value;
da.UpdateCommand = updateCommand;
conn.Open();
k = da.UpdateCommand.ExecuteNonQuery();
conn.Close();
}
if (k == 1)
MessageBox.Show("Done");
else
{
MessageBox.Show("Nothing Updated!");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
#endregion
#endregion
knowing that the compiler skips the loop in the update region.
At the second loop the query syntax becomes invalid cause the += that concatenates the previous text with the new one
Dim newQuery = ExQuery + row.Cells["Experiment"].Value.ToString() + "'";
And then use the new string for the ExecuteNonQuery.
Still this approach has many problems. You should separate this code in different methods and use parameters also for the last value
Have you tried to debug the foreach line to see if there are any rows in your dgvExperiments and if they are of type (or subtype of) DataGridViewRow ?

error: sql command not properly ended

I have to search the employee details, which is contained within 3 tables. I have used joins in the query query, but it shows error when I press the search button:
sql command not properly ended
c# coding:
try {
//Search Employee Details
Oracle.DataAccess.Client.OracleConnection cn = new Oracle.DataAccess.Client.OracleConnection();
cn.ConnectionString = "user id=system; password=system;";
Oracle.DataAccess.Client.OracleCommand cmd = new Oracle.DataAccess.Client.OracleCommand();
cmd.Connection = cn;
//cn = new Oracle.DataAccess.Client.OracleConnection();
cmd.CommandText = " select deposit.loanid,
form1.empedoj,
form1.empshare,
sharecapital.shareint,
sharecapital.loandt,
sharecapital.loandeduc,
sharecapital.dividend,
sharecapital.sharetot
from form1,
deposit,
sharecapital
where deposit.loanid(+) = sharecapital.loanid = '" + txtlnid.Text.Trim() + "'"; // shows sql command not properly ended
Oracle.DataAccess.Client.OracleDataAdapter ada = new Oracle.DataAccess.Client.OracleDataAdapter(cmd);
System.Data.DataTable dt = new DataTable();
dt.Clear();
ada.Fill(dt);
//Display in Textbox
if (dt.Rows.Count > 0) {
txtlnid.Text = dt.Rows[0].ItemArray[0].ToString();
admdate.Text = dt.Rows[0].ItemArray[1].ToString();
txtadmamt.Text = dt.Rows[0].ItemArray[2].ToString();
txtadmint.Text = dt.Rows[0].ItemArray[3].ToString();
loandt.Text = dt.Rows[0].ItemArray[4].ToString();
txtlnamt.Text = dt.Rows[0].ItemArray[5].ToString();
txtlnint.Text = dt.Rows[0].ItemArray[6].ToString();
txtsctot.Text = dt.Rows[0].ItemArray[7].ToString();
}
if (cn.State == ConnectionState.Closed) {
cn.Open();
}
string str;
str = cmd.ExecuteScalar().ToString();
if (str != null) {
MessageBox.Show("Record Found");
} else {
MessageBox.Show("ID not Match");
}
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
Your SQL statement becomes
SELECT DEPOSIT.LOANID,
FORM1.EMPEDOJ,
FORM1.EMPSHARE,
SHARECAPITAL.SHAREINT,
SHARECAPITAL.LOANDT,
SHARECAPITAL.LOANDEDUC,
SHARECAPITAL.DIVIDEND,
SHARECAPITAL.SHARETOT
FROM FORM1, DEPOSIT, SHARECAPITAL
WHERE DEPOSIT.LOANID(+) = SHARECAPITAL.LOANID = '" + txtlnid.Text.Trim() + "'";
I suspect it should be:
SELECT DEPOSIT.LOANID,
FORM1.EMPEDOJ,
FORM1.EMPSHARE,
SHARECAPITAL.SHAREINT,
SHARECAPITAL.LOANDT,
SHARECAPITAL.LOANDEDUC,
SHARECAPITAL.DIVIDEND,
SHARECAPITAL.SHARETOT
FROM FORM1, DEPOSIT, SHARECAPITAL
WHERE DEPOSIT.LOANID(+) = SHARECAPITAL.LOANID
AND SHARECAPITAL.LOANID = '" + txtlnid.Text.Trim() + "'";
Also, you have a 3-table join without the correct join conditions, the query is highly likely to return a Cartesian product.
Have you tried putting a semicolon at the end of your query string?
cmd.CommandText = " select deposit.loanid, form1.empedoj, form1.empshare,
sharecapital.shareint, sharecapital.loandt, sharecapital.loandeduc,
sharecapital.dividend, sharecapital.sharetot from form1, deposit ,
sharecapital where deposit.loanid(+) = sharecapital.loanid = '" + txtlnid.Text.Trim() + "';";

Categories

Resources