executenonquery not working, no columns edited - c#

I am trying to update my database. However when I print object that gets returned by ExecuteNonQuery() it says 0.
Here's my code:
try
{
using(dbConnection = new SqliteConnection(dbConnString))
{
dbConnection.Open();
using(dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = "UPDATE 'GameObject' SET 'LocationX' = #locX, 'LocationY' = #locY, 'LocationZ' = #locZ WHERE 'id' = #id";
dbCommand.Parameters.AddRange(new SqliteParameter[]
{
new SqliteParameter("#locX") { Value = x},
new SqliteParameter("#locY") { Value = y},
new SqliteParameter("#locZ") { Value = z},
new SqliteParameter("#id") {Value = id}
});
int i = dbCommand.ExecuteNonQuery();
Debug.Log(i);
}//end dbcommand
}//end dbconnection
}//end try
catch(Exception e)
{
Debug.Log(e);
}
I think it's because of my where clause, because when I add this clause to a select query, my variables won't get updated. I just can't find what's wrong with it.
select query:
try
{
using(dbConnection = new SqliteConnection(dbConnString))
{
dbConnection.Open();
using(dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = "SELECT * FROM 'GameObject' WHERE 'id' = #id"; //without the where everything works fine
dbCommand.Parameters.Add (new SqliteParameter("#id") { Value = 1});
using(dbReader = dbCommand.ExecuteReader())
{
while(dbReader.Read())
{
id = dbReader.GetInt32(0);
x = dbReader.GetFloat(1);
y = dbReader.GetFloat(2);
z = dbReader.GetFloat(3);
}
}//end dbreader
}//end dbcommand
}//end dbconnection
_object.transform.position = new Vector3(x,y,z);
Debug.Log ("id: " + id + " location: " + _object.transform.position);
}
catch(Exception e)
{
Debug.Log(e);
}

One reason might be from https://www.sqlite.org/lang_keywords.html
For resilience when confronted with historical SQL statements, SQLite
will sometimes bend the quoting rules above:
If a keyword in single quotes (ex: 'key' or 'glob') is used in a
context where an identifier is allowed but where a string literal is
not allowed, then the token is understood to be an identifier instead
of a string literal.
Since none of them is keyword, try to use them without single quotes.

Related

If the SELECT SQL Server value is null, the query takes 5 minutes C #

I have a very silly problem. I am doing a select, and I want that when the value comes null, return an empty string. When there is value in sql query, the query occurs all ok, but if there is nothing in the query, I have to give a sqlCommand.CommandTimeout greater than 300, and yet sometimes gives timeout. Have a solution for this?
public string TesteMetodo(string codPess)
{
var vp = new Classe.validaPessoa();
string _connection = vp.conString();
string query = String.Format("SELECT COUNT(*) FROM teste cliente WHERE cod_pess = {0}", codPess);
try
{
using (var conn = new SqlConnection(_connection))
{
conn.Open();
using (var cmd = new SqlCommand(query, conn))
{
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
return "";
return codPess;
}
}
}
You should probably validate in the UI and pass an integer.
You can combine the usings to a single block. A bit easier to read with fewer indents.
Always use parameters to make the query easier to write and avoid Sql Injection. I had to guess at the SqlDbType so, check your database for the actual type.
Don't open the connection until directly before the .Execute. Since you are only retrieving a single value you can use .ExecuteScalar. .ExecuteScalar returns an Object so must be converted to int.
public string TesteMetodo(string codPess)
{
int codPessNum = 0;
if (!Int32.TryParse(codPess, out codPessNum))
return "codPess is not a number";
var vp = new Classe.validaPessoa();
try
{
using (var conn = new SqlConnection(vp.conString))
using (var cmd = new SqlCommand("SELECT COUNT(*) FROM teste cliente WHERE cod_pess = #cod_pess", conn))
{
cmd.Parameters.Add("#cod_pess", SqlDbType.Int).Value = codPessNum;
conn.Open();
int count = (int)cmd.ExecuteScalar();
if (count > 0)
return "";
return codPess;
}
}
catch (Exception ex)
{
return ex.Message;
}
}

Error inserting a record and retrieving the autonumeric ID with OleDb

I am trying to make an oledb connection to an Access database to insert a new record and retrieving the key generated all at once. The code is this:
private static int createUser(OleDbConnection accessConn)
{
try
{
accessConn.Open();
//DbCommand also implements IDisposable
using (OleDbCommand cmd = accessConn.CreateCommand())
{
//create command with placeholders
cmd.CommandText =
"INSERT INTO EmployeeFiles " +
"([FirstName], [LastName], [JobTitleID], [SecurityLevel], [RowGUID])" +
"VALUES(#FirstName, #LastName, #JobTitleID, #SecurityLevel, #RowGUID)";
//Set Parameters
string FirstName = "Dick";
string LastName = "Tracy";
int JobTitleID = 11;
string SecurityLevel = "1";
string RowGUID = "{" + Guid.NewGuid() + "}";
//add named parameters
cmd.Parameters.AddRange(new OleDbParameter[]
{
new OleDbParameter("#FirstName", FirstName),
new OleDbParameter("#LastName", LastName),
new OleDbParameter("#JobTitleID", JobTitleID),
new OleDbParameter("#SecurityLevel", SecurityLevel),
new OleDbParameter("#RowGUID", RowGUID)
});
int userId = 0;
//Add #EmployeeID to the params collection and then retrieve it with Value
cmd.Parameters.Add("#EmployeeID", OleDbType.Integer).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
userId = (int)cmd.Parameters["#EmployeeID"].Value;
//userId = (int)cmd.ExecuteScalar();
Console.WriteLine("user created successfully: {0}", deliveryId);
return userId;
}
}
catch (Exception ex)
{
Console.WriteLine("Error: Failed creating the user.\n{0}", ex.Message);
return 0;
}
finally
{
accessConn.Close();
}
}
And when I run the code it throws this error:
System.Data.OleDb.OleDbDataAdapter internal error: invalid parameter accessor: 9 BADBINDINFO
I'm pretty sure the problematic line is this:
cmd.Parameters.Add("#EmployeeID", OleDbType.Integer).Direction = ParameterDirection.Output;
And I just don't get where is the mistake.
If I comment that and the next two lines, and uncomment this:
userId = (int)cmd.ExecuteScalar();
It throws the error: Object reference not set to an instance of an object
Is there a way to get this working with OleDbParameter? So far I'm being forced to make the insert and then a select to get the key generated.
I appreciate any suggestion.

Efficient Way to Update a lot of Rows from C#

I have a program where I open a SqlConnection, load up a list of objects, modify a value on each object, then update the rows in the SQL Server database. Because the modification requires string parsing I wasn't able to do with with purely T-SQL.
Right now I am looping through the list of objects, and running a SQL update in each iteration. This seems inefficient and I'm wondering if there is a more efficient way to do it using LINQ
The list is called UsageRecords. The value I'm updating is MthlyConsumption.
Here is my code:
foreach (var item in UsageRecords)
{
string UpdateQuery = #"UPDATE tbl810CTImport
SET MthlyConsumption = " + item.MthlyConsumption +
"WHERE ID = " + item.Id;
SqlCommand update = new SqlCommand(UpdateQuery, sourceConnection);
update.ExecuteNonQuery();
}
Try this instead:
string UpdateQuery = #"UPDATE tbl810CTImport SET MthlyConsumption = #consumption WHERE ID = #itemId";
var update = new SqlCommand(UpdateQuery, sourceConnection);
update.Parameters.Add("#consumption", SqlDbType.Int); // Specify the correct types here
update.Parameters.Add("#itemId", SqlDbType.Int); // Specify the correct types here
foreach (var item in UsageRecords)
{
update.Parameters[0].Value = item.MthlyConsumption;
update.Parameters[1].Value = item.Id;
update.ExecuteNonQuery();
}
It should be faster because:
You don't have to create the command each time.
You don't create a new string each time (concatenation)
The query is not parsed at every iteration (Just changes the parameters values).
And it will cache the execution plan. (Thanks to #JohnCarpenter from the comment)
You can either use
SqlDataAdapter - See How to perform batch update in Sql through C# code
or what I have previously done was one of the following:
Tear down the ID's in question, and re-bulkinsert
or
Bulk Insert the ID + new value into a staging table, and update the table on SQL server:
update u
set u.MthlyConsumption = s.MthlyConsumption
from tbl810CTImport u
inner join staging s on
u.id = s.id
In a situation like this, where you can't write a single update statement to cover all your bases, it's a good idea to batch up your statements and run more than one at a time.
var commandSB = new StringBuilder();
int batchCount = 0;
using (var updateCommand = sourceConnection.CreateCommand())
{
foreach (var item in UsageRecords)
{
commandSB.AppendFormat(#"
UPDATE tbl810CTImport
SET MthlyConsumption = #MthlyConsumption{0}
WHERE ID = #ID{0}",
batchCount
);
updateCommand.Parameters.AddWithValue(
"#MthlyConsumption" + batchCount,
item.MthlyConsumption
);
updateCommand.Parameters.AddWithValue(
"#ID" + batchCount,
item.MthlyConsumption
);
if (batchCount == 500) {
updateCommand.CommandText = commandSB.ToString();
updateCommand.ExecuteNonQuery();
commandSB.Clear();
updateCommand.Parameters.Clear();
batchCount = 0;
}
else {
batchCount++;
}
}
if (batchCount != 0) {
updateCommand.ExecuteNonQuery();
}
}
It should be as simple as this . . .
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Server=YourServerName;Database=YourDataBaseName;Trusted_Connection=True");
try
{
//cmd new SqlCommand( "UPDATE Stocks
//SET Name = #Name, City = #cit Where FirstName = #fn and LastName = #add";
cmd = new SqlCommand("Update Stocks set Ask=#Ask, Bid=#Bid, PreviousClose=#PreviousClose, CurrentOpen=#CurrentOpen Where Name=#Name", con);
cmd.Parameters.AddWithValue("#Name", textBox1.Text);
cmd.Parameters.AddWithValue("#Ask", textBox2.Text);
cmd.Parameters.AddWithValue("#Bid", textBox3.Text);
cmd.Parameters.AddWithValue("#PreviousClose", textBox4.Text);
cmd.Parameters.AddWithValue("#CurrentOpen", textBox5.Text);
con.Open();
int a = cmd.ExecuteNonQuery();
if (a > 0)
{
MessageBox.Show("Data Updated");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
con.Close();
}
}
Change the code to suit your needs.

What's wrong with my IF statement?

I'm creating an auditting table, and I have the easy Insert and Delete auditting methods done. I'm a bit stuck on the Update method - I need to be able to get the current values in the database, the new values in the query parameters, and compare the two so I can input the old values and changed values into a table in the database.
Here is my code:
protected void SqlDataSource1_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
string[] fields = null;
string fieldsstring = null;
string fieldID = e.Command.Parameters[5].Value.ToString();
System.Security.Principal. WindowsPrincipal p = System.Threading.Thread.CurrentPrincipal as System.Security.Principal.WindowsPrincipal;
string[] namearray = p.Identity.Name.Split('\\');
string name = namearray[1];
string queryStringupdatecheck = "SELECT VAXCode, Reference, CostCentre, Department, ReportingCategory FROM NominalCode WHERE ID = #ID";
string queryString = "INSERT INTO Audit (source, action, itemID, item, userid, timestamp) VALUES (#source, #action, #itemID, #item, #userid, #timestamp)";
using (SqlConnection connection = new SqlConnection("con string = deleted for privacy"))
{
SqlCommand commandCheck = new SqlCommand(queryStringupdatecheck, connection);
commandCheck.Parameters.AddWithValue("#ID", fieldID);
connection.Open();
SqlDataReader reader = commandCheck.ExecuteReader();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount - 1; i++)
{
if (reader[i].ToString() != e.Command.Parameters[i].Value.ToString())
{
fields[i] = e.Command.Parameters[i].Value.ToString() + "Old value: " + reader[i].ToString();
}
else
{
}
}
}
fieldsstring = String.Join(",", fields);
reader.Close();
SqlCommand command = new SqlCommand(queryString, connection);
command.Parameters.AddWithValue("#source", "Nominal");
command.Parameters.AddWithValue("#action", "Update");
command.Parameters.AddWithValue("#itemID", fieldID);
command.Parameters.AddWithValue("#item", fieldsstring);
command.Parameters.AddWithValue("#userid", name);
command.Parameters.AddWithValue("#timestamp", DateTime.Now);
try
{
command.ExecuteNonQuery();
}
catch (Exception x)
{
Response.Write(x);
}
finally
{
connection.Close();
}
}
}
The issue I'm having is that the fields[] array is ALWAYS null. Even though the VS debug window shows that the e.Command.Parameter.Value[i] and the reader[i] are different, the fields variable seems like it's never input into.
Thanks
You never set your fields[] to anything else than null, so it is null when you are trying to access it. You need to create the array before you can assign values to it. Try:
SqlDataReader reader = commandCheck.ExecuteReader();
fields = new string[reader.FieldCount]
I don't really understand what your doing here, but if your auditing, why don't you just insert every change into your audit table along with a timestamp?
Do fields = new string[reader.FieldCount] so that you have an array to assign to. You're trying to write to null[0].

System.Data.SQLite parameter issue

I have the following code:
try
{
//Create connection
SQLiteConnection conn = DBConnection.OpenDB();
//Verify user input, normally you give dbType a size, but Text is an exception
var uNavnParam = new SQLiteParameter("#uNavnParam", SqlDbType.Text) { Value = uNavn };
var bNavnParam = new SQLiteParameter("#bNavnParam", SqlDbType.Text) { Value = bNavn };
var passwdParam = new SQLiteParameter("#passwdParam", SqlDbType.Text) {Value = passwd};
var pc_idParam = new SQLiteParameter("#pc_idParam", SqlDbType.TinyInt) { Value = pc_id };
var noterParam = new SQLiteParameter("#noterParam", SqlDbType.Text) { Value = noter };
var licens_idParam = new SQLiteParameter("#licens_idParam", SqlDbType.TinyInt) { Value = licens_id };
var insertSQL = new SQLiteCommand("INSERT INTO Brugere (navn, brugernavn, password, pc_id, noter, licens_id)" +
"VALUES ('#uNameParam', '#bNavnParam', '#passwdParam', '#pc_idParam', '#noterParam', '#licens_idParam')", conn);
insertSQL.Parameters.Add(uNavnParam); //replace paramenter with verified userinput
insertSQL.Parameters.Add(bNavnParam);
insertSQL.Parameters.Add(passwdParam);
insertSQL.Parameters.Add(pc_idParam);
insertSQL.Parameters.Add(noterParam);
insertSQL.Parameters.Add(licens_idParam);
insertSQL.ExecuteNonQuery(); //Execute query
//Close connection
DBConnection.CloseDB(conn);
//Let the user know that it was changed succesfully
this.Text = "Succes! Changed!";
}
catch(SQLiteException e)
{
//Catch error
MessageBox.Show(e.ToString(), "ALARM");
}
It executes perfectly, but when I view my "brugere" table, it has inserted the values: '#uNameParam', '#bNavnParam', '#passwdParam', '#pc_idParam', '#noterParam', '#licens_idParam' literally. Instead of replacing them.
I have tried making a breakpoint and checked the parameters, they do have the correct assigned values. So that is not the issue either.
I have been tinkering with this a lot now, with no luck, can anyone help?
Oh and for reference, here is the OpenDB method from the DBConnection class:
public static SQLiteConnection OpenDB()
{
try
{
//Gets connectionstring from app.config
const string myConnectString = "data source=data;";
var conn = new SQLiteConnection(myConnectString);
conn.Open();
return conn;
}
catch (SQLiteException e)
{
MessageBox.Show(e.ToString(), "ALARM");
return null;
}
}
You should remove the quotes around your parameter names in the INSERT statement.
So instead of
VALUES ('#uNameParam', '#bNavnParam', '#passwdParam', '#pc_idParam',
'#noterParam', '#licens_idParam')
use
VALUES (#uNameParam, #bNavnParam, #passwdParam, #pc_idParam,
#noterParam, #licens_idParam)
Thanks to rwwilden and Jorge Villuendas, the answer is:
var insertSQL = new SQLiteCommand("INSERT INTO Brugere (navn, brugernavn, password, pc_id, noter, licens_id)" +
" VALUES (#uNavnParam, #bNavnParam, #passwdParam, #pc_idParam, #noterParam, #licens_idParam)", conn);
insertSQL.Parameters.AddWithValue("#uNavnParam", uNavn);
insertSQL.Parameters.AddWithValue("#bNavnParam", bNavn);
insertSQL.Parameters.AddWithValue("#passwdParam", passwd);
insertSQL.Parameters.AddWithValue("#pc_idParam", pc_id);
insertSQL.Parameters.AddWithValue("#noterParam", noter);
insertSQL.Parameters.AddWithValue("#licens_idParam", licens_id);
insertSQL.ExecuteNonQuery(); //Execute query
When you use System.Data.SqlClient then you provide parameter types from System.Data.SqlDbType enumeration.
But if you use System.Data.SQLite then you have to use **System.Data.DbType** enumeration.
replace
VALUES ('#uNameParam', '#bNavnParam',
'#passwdParam', '#pc_idParam',
'#noterParam', '#licens_idParam')
with
VALUES (?, ?, ?, ?, ?, ?)

Categories