Updating a table row with OleDB from C# - c#

I am working on an invoice managament application that draws information from an Access database (modern .accdb format) and getting the data works fine, but when I try to update it (following some tutorials, or should I say answers, nothing works..
What is wrong with this code, it... should work.
public int UpdateDBBill(Bill bill)
{
using (var connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\BC.accdb"))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Bills SET Payer = #Payer, Category = #Category, Recipient = #Recipient, Currency = #Currency, Amount = #Amount, IBANOfRecipient = #IBANOfRecipient, Model = #Model, ReferenceNumber = #ReferenceNumber, Description = #Description, DueDate = #DueDate, ForMonth = #ForMonth, Paid = #Paid, DatePaid = #DatePaid WHERE Id = #Id";
command.Parameters.AddWithValue("#Payer", bill.Payer);
command.Parameters.AddWithValue("#Category", bill.Category);
command.Parameters.AddWithValue("#Recipient", bill.Recipient);
command.Parameters.AddWithValue("#Currency", bill.Currency);
command.Parameters.AddWithValue("#Amount", bill.amount);
command.Parameters.AddWithValue("#IBANOfRecipient", bill.IBANOfRecipient);
command.Parameters.AddWithValue("#Model", bill.Model);
command.Parameters.AddWithValue("#ReferenceNumber", bill.ReferenceNumber);
command.Parameters.AddWithValue("#Description", bill.Description);
command.Parameters.AddWithValue("#DueDate", bill.DueDate);
command.Parameters.AddWithValue("#ForMonth", bill.ForMonth);
command.Parameters.AddWithValue("#Paid", bill.Paid);
command.Parameters.AddWithValue("#DatePaid", bill.DatePaid);
command.Parameters.AddWithValue("#Id", bill.Id);
try
{
return command.ExecuteNonQuery();
}
catch
{
return -1;//for error
}
}
}
Answer:
public int UpdateDBBill(Bill bill)
{
using (var connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\BC.accdb"))
using (var command = connection.CreateCommand())
{
connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Bills SET Payer = #Payer, Category = #Category, Recipient = #Recipient, [Currency] = #Currency, Amount = #Amount, IBANOfRecipient = #IBANOfRecipient, [Model] = #Model, ReferenceNumber = #ReferenceNumber, DueDate = #DueDate, ForMonth = #ForMonth, Paid = #Paid, DatePaid = #DatePaid WHERE Id = #Id";
command.Parameters.Add("#Payer", OleDbType.VarChar).Value = bill.Payer;
command.Parameters.Add("#Category", OleDbType.VarChar).Value = bill.Category;
command.Parameters.Add("#Recipient", OleDbType.VarChar).Value = bill.Recipient;
command.Parameters.Add("#Currency", OleDbType.VarChar).Value = bill.Currency;
command.Parameters.Add("#Amount", OleDbType.VarChar).Value = bill.GetAmount();
command.Parameters.Add("#IBANOfRecipient", OleDbType.VarChar).Value = bill.IBANOfRecipient;
command.Parameters.Add("#Model", OleDbType.VarChar).Value = bill.Model;
command.Parameters.Add("#ReferenceNumber", OleDbType.VarChar).Value = bill.ReferenceNumber;
command.Parameters.Add("#DueDate", OleDbType.Date).Value = bill.DueDate.Date;
command.Parameters.Add("#ForMonth", OleDbType.Date).Value = bill.ForMonth.Date;
command.Parameters.Add("#Paid", OleDbType.Boolean).Value = bill.Paid;
command.Parameters.Add("#DatePaid", OleDbType.Date).Value = bill.DatePaid.Date;
command.Parameters.Add("#Id", OleDbType.Integer).Value = bill.Id;
try
{
int Rows = command.ExecuteNonQuery();
return Rows;
}
catch
{
return -1;//for error
}
}
}

With OleDb the position of the parameters matters a lot.
OleDb doesn't associate parameters' placeholders with the parameters' names but follows a strictly positional order. So, your query is correct, but when you add the parameters to the collection you should follow the parameter placeholders order.
command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Bills SET ([Payer] = #Payer, [Category] = #Category, ...) WHERE Id = #Id";
command.Parameters.AddWithValue("#Payer", bill.Payer);
command.Parameters.AddWithValue("#Category", bill.Category);
....
command.Parameters.AddWithValue("#Id", bill.Id);
With Access you can name your parameters as you do for its big cousin Sql Server albeit the OleDb docs say that you should use the question mark as parameter placeholder, however the names are simply ignored when the OleDb provider associates the values to the placeholders.
As a side note, consider that AddWithValue is an handy but dangerous method. The parameter type is extracted by the value passed and sometimes this could create a 'DataType mismatch Exception' or wrong conversions (in particular if you pass dates or decimals as strings to AddWithValue)
See Can we stop using AddWithValue already?
EDIT After a long debug session in chat the final problem is identified in the Currency field written withot brackets. Currency is a reserved words in Access and should be enclosed in square bracket. This was not initially evident because the first query proposed by the OP was correctly typed with square bracket but then the square brackets disappeared from the query for whatever reason. The suggestion to NOT use AddWithValue stands to avoid unnecessary conversions from dates to strings and then back to strings....
command.CommandText = "UPDATE Bills SET ([Payer] = #Payer, [Category] = #Category, ...) WHERE Id = #Id";
command.Parameters.Add("#Payer", OleDbType.VarWChar).Value = bill.Payer;
command.Parameters.Add("#Category", OleDbType.VarWChar).Value = bill.Category;
....
command.Parameters.Add("#DueDate", OleDbType.Date).Value = bill.DueDate.Date;
....
command.Parameters.Add("#Id", OleDbType.Integer).Value = bill.Id;

I came across with this before. My issue was, I was not providing the parameters in the order they were present in the query.
In your case, as your update goes on with parameters Payer, Category...,Id your AddWithValues should follow the same order.
I hope this helps

Ok... I found the issue.
First of all, you should put the Currency field in brackets because Access considers it as a datatype if you don't and you get Syntax error.
Then, keep all AddWithValue statements order untouched.
Finally, while adding date fields (DueDate, ForMonth and DatePaid), use ToString("yyyy-MM-dd") so that Access will interpret the value as date. Also, parse the amount field to double.
Below is my version of the code. Hope this will work :)
command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Bills SET Payer = #Payer, Category = #Category, Recipient = #Recipient, [Currency] = #Currency, Amount = #Amount, IBANOfRecipient = #IBANOfRecipient, Model = #Model, ReferenceNumber = #ReferenceNumber, Description = #Description, DueDate = #DueDate, ForMonth = #ForMonth, Paid = #Paid, DatePaid = #DatePaid WHERE Id = #Id";
command.Parameters.AddWithValue("#Payer", bill.Payer);
command.Parameters.AddWithValue("#Category", bill.Category);
command.Parameters.AddWithValue("#Recipient", bill.Recipient);
command.Parameters.AddWithValue("#Currency", bill.Currency);
command.Parameters.AddWithValue("#Amount", Convert.ToDouble(bill.amount));
command.Parameters.AddWithValue("#IBANOfRecipient", bill.IBANOfRecipient);
command.Parameters.AddWithValue("#Model", bill.Model);
command.Parameters.AddWithValue("#ReferenceNumber", bill.ReferenceNumber);
command.Parameters.AddWithValue("#Description", bill.Description);
command.Parameters.AddWithValue("#DueDate", bill.DueDate.ToString("yyyy-MM-dd"));
command.Parameters.AddWithValue("#ForMonth", bill.ForMonth.ToString("yyyy-MM-dd"));
command.Parameters.AddWithValue("#Paid", bill.Paid);
command.Parameters.AddWithValue("#DatePaid", bill.DatePaid.ToString("yyyy-MM-dd"));
command.Parameters.AddWithValue("#Id", bill.Id);
try
{
return command.ExecuteNonQuery();
}
catch
{
return -1;//for error
}

Related

Unable to update Number type column of Oracle database

I am trying to update a column of type Number(19, 2) in my Oracle database using following code in C#. However, it does not update the data in the table. Amount - is of type Number(19,2) in database and I tried replacing Varchar2 with decimal, Int64, Long but still no luck. And request.amount is of a float type.
Any tips would be highly appreciated. Thanks
try
{
OracleCommand command2 = new OracleCommand();
command2.CommandText = "Update t_payment set amount = :amount where penalty_order_id = (select id from t_penalty_order where protokol_no = :invoiceNumber)";
command2.Parameters.Add(new OracleParameter(#"invoiceNumber", OracleDbType.Varchar2, 255)).Value = request.invoiceNumber;
command2.Parameters.Add(new OracleParameter(#"amount", OracleDbType.Varchar2, 255)).Value = request.amount; //(Convert.ToInt32 (request.amount) + paid_amount);
command2.Connection = connection;
command2.CommandType = System.Data.CommandType.Text;
command2.ExecuteNonQuery();
}
catch (Exception e)
{
completePayment.code = 111;
completePayment.message = e.Message;
completePayment.transactionNumber = null;
}
I found the problem. It was in the order of adding parameters. I had to add amount parameter value first and then protokol_no.

simple update query doesn't work, but when i put it into database itself it does work

When i run my code in the debugger and I hover my mouse over the parameters they do have the right values in them. It just doesn't update my database but when I copy the query and put it into the database it works without a problem.
The parameter values are:
id = 7
omschrijving = douche muntjes
prijs = 0,5
catagorie = faciliteiten
I checked the connection tring by using an insert query and that does add records to my database. And There is an id with the value of 7 in the database.
When I run a insert query or a delete query through my C# code it does work it's just the update statement that doesn't work. If anyone sees the issue please help me.
public static void wijzigprijs(int id, string omschrijving, decimal prijs, string catagorie)
{
try
{
try
{
OleDbConnection verbinding = new OleDbConnection(
#"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=..\..\..\La_Rustique.accdb;
Persist Security Info=False;");
verbinding.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
OleDbCommand query = new OleDbCommand();
query.CommandText = #"UPDATE prijslijst
SET omschrijving = #omschrijving,
prijs = #prijs,
catagorie = #catagorie
WHERE id = #id";
query.Parameters.Add(new OleDbParameter("#id", OleDbType.Integer));
query.Parameters["#id"].Value = id;
query.Parameters.Add(new OleDbParameter("#omschrijving", OleDbType.VarChar));
query.Parameters["#omschrijving"].Value = omschrijving;
query.Parameters.Add(new OleDbParameter("#prijs", OleDbType.Decimal));
query.Parameters["#prijs"].Value = prijs;
query.Parameters.Add(new OleDbParameter("#catagorie", OleDbType.VarChar));
query.Parameters["#catagorie"].Value = catagorie;
query.Connection = verbinding;
query.ExecuteNonQuery();
MessageBox.Show("succesvol gewijzigd");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
verbinding.Close();
}
}
EDIT UPDATE
Look at this topic. Here he explains how you should use variables with OleDbCommand
Variables with OleDbCommand
This is how you typically will do it when using SQLCommand parameters:
I know this doesnt answer your questions quite, but when i use SQLCommand i use this code whenever i want to update or insert with variables:
string query = #"UPDATE prijslijst
SET omschrijving = #omschrijving,
prijs = #prijs,
catagorie = #catagorie
WHERE id = #id";
SqlCommand cmd = new SqlCommand(query, connDatabase);
cmd.Parameters.Add("#id", SqlDbType.integer).Value = 7;
cmd.ExecuteNonQuery();
connDatabase.Close();
So you should be able to do the samething. Hope this will help you.
I have never seen OleDB queries written in the above syntax.
To state it differently: OleDB simply does not use named parameters, it uses the position only.
Try to change your SQL statement like this:
query.CommandText = #"UPDATE prijslijst
SET omschrijving = ?,
prijs = ?,
catagorie = ?
WHERE id = ?";
and then add the parameters in sequence of above in the code
below that.

SQL Query incorrect syntax error c#

I'm getting the following error
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Incorrect syntax near the keyword 'Group'.
When I run the following query
string query = "Update Job Set Name = #Name, Date = #Date, Material = #Material, Instructions = #Instructions, Group = #Group, Time = #Time, Address = #Address Where Id = #Id";
DataRowView drv = (DataRowView)jobGrid.Items.GetItemAt(0);
string name = drv.Row[0].ToString();
int Id = getId(name);
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
string date = drv.Row[1].ToString();
string material = drv.Row[2].ToString();
string details = drv.Row[3].ToString();
string group = drv.Row[4].ToString();
string time = drv.Row[5].ToString();
string address = drv.Row[6].ToString();
command.Parameters.AddWithValue("#Name", name);
command.Parameters.AddWithValue("#Date", date);
command.Parameters.AddWithValue("#Material", material);
command.Parameters.AddWithValue("#Instructions", details);
command.Parameters.AddWithValue("#Group", group);
command.Parameters.AddWithValue("#Time", time);
command.Parameters.AddWithValue("#Address", address);
command.Parameters.AddWithValue("#Id", Id);
command.ExecuteNonQuery();
}
All of those things exist in the database in that order except for Id which comes first. I run a similar update using a different table in the database and it works perfectly. I'm not sure what is wrong with "Group" that makes that error. The value that I insert into Group is a string which is specified by the table ass varchar(50). I am using Visual Studio WPF c#
I can add and delete things from this table perfectly fine, but updating causes this issue
Use brackets for reserved keywords like Date,Group,Time etc
Update Job Set Name = #Name, [Date] = #Date, Material = #Material, Instructions = #Instructions, [Group] = #Group, [Time] = #Time, Address = #Address Where Id = #Id
check Reserved Keywords (Transact-SQL)
You have to use square brackets for reserved keywords
Try this: Update Job Set Name = #Name, [Date] = #Date, Material = #Material, Instructions = #Instructions, [Group] = #Group, [Time] = #Time, Address = #Address Where Id = #Id

Must declare the scalar variable "#ID" for insert parameter

I am receiving the error, Must declare the scalar variable "#ID". Pointing at ExecuteScalar line. I looked on goggle and I think it has something to do with insert parameters for ID. Then again I read there could be a typo error. In my db I have declare column name as ID and Data Type as int, setting 'Is Identity' as Yes. As I am not going to insert ID column manually I think this is why I am having problem(s) and I don't know how to solve this problem.
What I am trying to do is insert username, login date and time. Update on the same column (same id column) when user logs out. Create a new column when user log in again and So on. I am using the similar code that I asked here and here when D Stanley helped me.
Thanks in advance if anyone can help me.
private int ID // forgot to add this.
{ get; set; }
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
string value = cbRoles.Text;
switch (value)
{
case "Manager":
myCon.connectionString();
string dString = string.Empty;
SqlConnection thisConnection = myCon.dbCon;
SqlCommand nonqueryCommand = thisConnection.CreateCommand();
using (var command = myCon.dbCon.CreateCommand())
{
command.CommandText = "SELECT * FROM tblPrivileges";
command.Parameters.AddWithValue("UserName", (txtUserName.Text));
command.Parameters.AddWithValue("Password", (txtPassword.Text));
thisConnection.Open();
var reader = command.ExecuteReader(); //strcomp
{
if (reader.HasRows)
{
while (reader.Read())
{
txtUserName.Text = reader["UserName"].ToString();
txtPassword.Text = reader["Password"].ToString();
MainWindow gobackB = new MainWindow();
gobackB.Show();
LoginSample goback = new LoginSample();
goback.Hide();
}
}
else MessageBox.Show("You have entered incorrect credentials. Please try again", "error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
myCon.dbCon.Close();
nonqueryCommand.CommandType = CommandType.Text;
nonqueryCommand.CommandText = "INSERT tblLoginLogTable (UserName, LoggedInDate, LoggedInTime) VALUES (#UserName, #LoggedInDate, #LoggedInTime)";
//nonqueryCommand.Parameters.AddWithValue("#ID", SqlDbType.Int); this did not work
//nonqueryCommand.Parameters["#ID"].Value = this.ID; this did not work
nonqueryCommand.Parameters.AddWithValue("#UserName", txtUserName.Text);
nonqueryCommand.Parameters.AddWithValue("#LoggedInDate", DateTime.Now);
nonqueryCommand.Parameters.AddWithValue("#LoggedInTime", DateTime.Now.ToString("HH:mm"));
thisConnection.Open();
nonqueryCommand.ExecuteNonQuery(); // error pointing here
nonqueryCommand.CommandText = "SELECT #ID = SCOPE_IDENTITY()";
int id = (int)nonqueryCommand.ExecuteScalar();
// int id = Convert.ToInt32(nonqueryCommand.ExecuteScalar()); this line did not work
this.ID = id;
myCon.dbCon.Close();
break;
The problem is still that you're trying to use the same "scope" with two different SQL commands. Even thought they are the same "variable" in C# in SQL they have different scope.
You'll need to execute both statements in one command and add the #ID parameter as an Output parameter in order to insert and get the identity out:
nonqueryCommand.CommandType = CommandType.Text;
nonqueryCommand.CommandText = "INSERT tblLoginLogTable (UserName, LoggedInDate, LoggedInTime) VALUES (#UserName, #LoggedInDate, #LoggedInTime); " +
"SELECT #ID = SCOPE_IDENTITY()";
nonqueryCommand.Parameters.AddWithValue("#UserName", txtUserName.Text);
nonqueryCommand.Parameters.AddWithValue("#LoggedInDate", DateTime.Now);
nonqueryCommand.Parameters.AddWithValue("#LoggedInTime", DateTime.Now);
nonqueryCommand.Parameters.Add("#ID",SqlDbType.Int).Direction = ParameterDirection.Output;
thisConnection.Open();
nonqueryCommand.ExecuteNonQuery();
int id = (int)nonqueryCommand.Parameters["#ID"];
Here:
nonqueryCommand.CommandText = "SELECT #ID = SCOPE_IDENTITY()";
your SQL assigns a value to a variable that is not declared. Since you are using ExecuteScalar, you probably just mean:
nonqueryCommand.CommandText = "SELECT SCOPE_IDENTITY()";
Note that you might need to cast it - it may come back as decimal.

Retrieve the last id from the SQL Server database table

How do I get the last id created in the policy table and store it into a variable so that I can use it for another table called backupspec table.
System.Data.SqlClient.SqlConnection dataConnection = new SqlConnection();
dataConnection.ConnectionString =
#"Data Source=JAGMIT-PC\SQLEXPRESS;Initial Catalog=SumooHAgentDB;Integrated Security=True";
System.Data.SqlClient.SqlCommand dataCommand = new SqlCommand();
dataCommand.Connection = dataConnection;
//tell the compiler and database that we're using parameters (thus the #first, #last, #nick)
dataCommand.CommandText = ("Insert Policies ( PolicyName, PolicyDesc, TimeAdded,OSFlag, CreateVSSSnapshot, CreateAuditLogForRecoveries, AllowUsersToOverwriteFiles, AutoHandleEnvErrors, NotifyOnEnvErrorCount, NotifyOnFileFailure, NotifyOnFileFailureCount, NotifyOnLackOfPCContact, NotifyOnLackOfPCContactDays, NotifyOnRecoveryFailures, NotifyOnRecoveryFailureReason) values (#pn,#pd,#TimeAdded,#os,#vss,#al,#uow,#hee,#oeec,#off,#offc,#oloc,#olocd,#orf,#orfr)");
dataCommand.Parameters.AddWithValue("#pn",pn);
dataCommand.Parameters.AddWithValue("#pd",pd);
dataCommand.Parameters.AddWithValue("#TimeAdded",TimeAdded);
dataCommand.Parameters.AddWithValue("#os",os);
dataCommand.Parameters.AddWithValue("#vss",vss);
dataCommand.Parameters.AddWithValue("#al",al);
dataCommand.Parameters.AddWithValue("#uow",uow);
dataCommand.Parameters.AddWithValue("#hee",hee);
dataCommand.Parameters.AddWithValue("#oeec",oeec);
dataCommand.Parameters.AddWithValue("#off",off);
dataCommand.Parameters.AddWithValue("#offc",offc);
dataCommand.Parameters.AddWithValue("#oloc",oloc);
dataCommand.Parameters.AddWithValue("#olocd",olocd);
dataCommand.Parameters.AddWithValue("#orf",orf);
dataCommand.Parameters.AddWithValue("#orfr",orfr);
dataConnection.Open();
dataCommand.ExecuteNonquery();
dataConnection.Close();
ArrayList jaja = (ArrayList)Session["BackupSpecList"];
for (int i = 0; i < jaja.Count; i++)
{
BackupSpecEntry bsp = (BackupSpecEntry)jaja[i];
string path = bsp.path;
string inclExcl = bsp.inclExcl;
byte inclExclFlags = bsp.inclExclFlags;
bool indexContents = bsp.indexContents;
int serverBackupSpecId = bsp.serverBackupSpecId;
int freq = bsp.freq;
int retention = bsp.retention;
int policyID =DONT KNOW HOW TO GET THIS VALUE;
long specChangeTime = 0;
long backupTime = 0;
dataCommand.CommandText = ("Insert BackupSpec (PolicyID, Path, ServerBackupSpecID, Freq, Retention, InclExclFlags, InclExcl, IndexContents, SpecChangeTime, BackupTime) values (#policyID,#path,#serverBackupSpecId,#freq,#retention,#inclExclFlags,#inclExcl,#indexContents,#specChangeTime,#backupTime)");
dataCommand.Parameters.AddWithValue("#policyID", policyID);
dataCommand.Parameters.AddWithValue("#path", path);
dataCommand.Parameters.AddWithValue("#serverBackupSpecId", serverBackupSpecId);
dataCommand.Parameters.AddWithValue("#freq", freq);
dataCommand.Parameters.AddWithValue("#retention", retention);
dataCommand.Parameters.AddWithValue("#inclExclFlags", inclExclFlags);
dataCommand.Parameters.AddWithValue("#inclExcl", inclExcl);
dataCommand.Parameters.AddWithValue("#indexContents", indexContents);
dataCommand.Parameters.AddWithValue("#specChangeTime", specChangeTime);
dataCommand.Parameters.AddWithValue("#backupTime", backupTime);
dataConnection.Open();
dataCommand.ExecuteNonQuery();
dataConnection.Close();
}
I am getting error with the label id...
can some 1 help me with this..??
I am not getting the last policyID created after inserting please help...
Please help
Use scope_identity:
strSQL = "INSERT INTO Policies (...) VALUES (#vals....);SELECT #result = scope_identity()"
SQLCommand.CommandText = strSQL;
SQLCommand.Parameters.Add("#result", SqlDbType.Int);
SQLCommand.ExecuteScalar();
int id = SQLCommand.Parameters["#result"].Value;
You can use either SCOPE_IDENTITY or ##IDENTITY
SCOPE_IDENTITY:
strSQL = "INSERT INTO Policies (...) VALUES (#vals....);SELECT SCOPE_IDENTITY()";
SQLCommand.CommandText = strSQL;
IdReturned = SQLCommand.ExecuteScalar();
##IDENTITY:
strSQL = "INSERT INTO Policies (...) VALUES (#vals....);SELECT ##Identity";
SQLCommand.CommandText = strSQL;
IdReturned = SQLCommand.ExecuteScalar();
For the differences between the two i recommend reading this article
If you do a INSERT INTO Policies() call first, in order to get the lastid, you could do something like this:
int lastId = 0;
using(SqlConnection Connection = new SqlConnection("(connection string)"))
{
string queryStatement =
"INSERT INTO dbo.Policies(fields) OUTPUT Inserted.LastID VALUES(....)";
using(SqlCommand Command = new SqlCommand(queryStatement, Connection))
{
Connection.Open();
lastId = Command.ExecuteScalar();
Connection.Close();
}
}
Use the OUTPUT ....... clause to return the newly inserted lastId.
Then go on and use that value in your main query.
Marc

Categories

Resources