I have a parameterized query and it was working fine, but when I delete de DB and create it again, with the same values and everything, it throws an exception that says it cannot insert value NULL with the value sexo, but all the values are assigned, here it's the code:
try{
var cmdPersona_Log = new SqlCommand();
cmdPersona_Log.Parameters.Clear();
cmdPersona_Log.Connection = mySqlConnection;
cmdPersona_Log.CommandType = CommandType.Text;
cmdPersona_Log.CommandText = #"INSERT INTO [Tomin].[TominRH].[Persona_Log] "
+ "([Id_Action],[Id_User],[Id_Date],[Id_Entidad],[Nombre],[Paterno],[Materno],[Sexo],[Id_Nacionalidad])"
+ " Values (1, 'Admin', #fecha, #id_entidad, #nombre, #paterno, #materno, #sexo, 52)";
cmdPersona_Log.Parameters.AddWithValue("#fecha", DateTime.Now);
cmdPersona_Log.Parameters.AddWithValue("#id_entidad", dbRow["CUENTA"].ToString().Trim());
cmdPersona_Log.Parameters.AddWithValue("#nombre", nombre ?? string.Empty);
cmdPersona_Log.Parameters.AddWithValue("#paterno", paterno ?? string.Empty);
cmdPersona_Log.Parameters.AddWithValue("#materno", materno ?? string.Empty);
cmdPersona_Log.Parameters.AddWithValue("#sexo", 1);
cmdPersona_Log.ExecuteNonQuery();
}
catch(Exception e)
{
MessageBox.Show(dbRow["CUENTA"] + " Persona_log " + e.ToString());
}
I've checked the DB and it doesn't seem to be the problem, any sugestion??
You may be running into a case where AddWithValue isn't inferring your parameter type of bit properly. Use true/false instead of 1/0:
cmdPersona_Log.Parameters.AddWithValue("#sexo", true);
Make sure that all fields of the table which are supposed to be not null are listed in the INSERT-clause
Have you tried using this form
cmd.Parameters.Add("#SomeID", SqlDbType.Int, 4).Value =
where you can be explicit about the SqlDbType?
Related
I am currently in a corner and have no idea why the following code will not execute properly and update the database (Access).
newUser = All of the new user's data including their ID
list = Contains a list of GermanResources (class) entries that correspond to the pages checkboxes. Class includes .Name (text value of checkbox) and .Value (checked? 1 or 0)
I want to update the database with the checkbox value of each GermanResource.
IF i replace #acc_Value with the value 1 this code works. It seems to not work with the first parameter in place. Debugging this showed me that everything had the proper values at the proper times and since "1" worked I know the data types are not mismatched.
Note: There were no errors with or without the parameter in place.
I would appreciate any input about this.
This is one of the CommandTexts that are generated:
UPDATE VMS_GRM_GermanResource_Access SET VTOFZN = #acc_Value WHERE UserId = #userId
private bool NewUser_Insert_GermanResourceAccess(OleDbConnection connection, User newUser, List<GermanResource> list)
{
bool result = false;
try
{
foreach (var item in list)
{
string column = item.Name.Replace(" ", "");
string query = #"UPDATE VMS_GRM_GermanResource_Access SET " + column + " = #acc_Value WHERE UserId = #userId";
OleDbCommand command = new OleDbCommand(query, connection);
command.Parameters.AddWithValue("#userId", newUser.Id);
command.Parameters.Add(new OleDbParameter("#acc_Value", OleDbType.Integer, 1));
command.Parameters["#acc_Value"].Value = item.Access;
command.ExecuteNonQuery();
}
result = true;
}
catch (OleDbException ex)
{
UADConnection.Close();
MessageBox.Show(ex.ErrorCode.ToString() + ": " + ex.Message);
return result;
}
return result;
}
Use this to prepare sql statement :-
string query = #"UPDATE VMS_GRM_GermanResource_Access SET column_name=" +
#acc_Value + " WHERE UserId = " +#userId+";
#Tetsuya Yamamoto:
OLEDB parameters were not in order according to the query. Swapping them around to match the order in the query set things straight. All good again and thanks for everyone's inputs.
I am making DatabaseManager class for my solution and I am getting the number 0 when I am trying to update the text.
For example : I have now the name michael and I wanted to change it to "michael , mike" so I'll probably use update.
public void AddCrime(CSteamID id, string crime, string time)
{
try
{
MySqlConnection connection = createConnection();
MySqlCommand command = connection.CreateCommand();
crime = "," + crime;
command.CommandText = "update `" + Main.Instance.Configuration.Instance.DatabaseTableName
+ "` set `crime` = crime + ( #crime ) where `steamId` = #steamID; select `crime` from `"
+ Main.Instance.Configuration.Instance.DatabaseTableName
+ "` where `steamId` = #steamID";
command.Parameters.AddWithValue("#steamID", id);
command.Parameters.AddWithValue("#crime", crime);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
AddTime(id, time);
}
catch (Exception ex) { Logger.Log(ex); }
}
How do I call it :
DatabaseManager.AddWanted(player.CSteamID, command[1], command[2]);
Thanks everyone!
yor last sentence in your command is a select statement, NonQuery does not return values, only the number of rows affected. Change it to ExecuteScalar and store the value of the select in a variable.
Second error is the data type of the parameter #steamID. You set the value id, which is declares as CSteamID id... CStreamId is not string, change the AddWithValue
Fixed, I added another method to get crime from table and then changed the void crime string to the current string + the table text.
The error was : Truncated incorrect DOUBLE value.
"AND TT.[_TYPE] = CASE WHEN " + String.IsNullOrEmpty(lstTypeSearch.SelectedItem) ?
DBNull.Value} +
" IS NULL THEN TT.[_TYPE] ELSE " + lstTypeSearch.SelectedItem + " END ";
Above is a pseudo aspect of my query.
I need to do a validation of listbox item for null and then set as DBNull.Value, which is to be passed into CASE WHEN within SQL Query.
Any better way to achieve this? I am getting tons of String to Bool, Null to String conversion errors...
Further, is there anyway to pass DBNull.Value as a Parameter across data access layer?
EDIT: original query is in a Static class.
public static readonly string SqlGetItemsBy_Number_Capacity_Type =
"SELECT TT.[_NUMBER], " +
"TT.[CAPACITY], " +
"TT.[_TYPE], " +
"TS.[SESSIONE] " +
"FROM [ITEMS] AS TT, //some code
"WHERE //some code
"AND TT.[_TYPE] = CASE WHEN #Type IS NULL THEN TT.[_TYPE] ELSE #Type END";
If I run the same query in SQL Server, it works fine.
SELECT //some code
AND [_TYPE] = CASE WHEN NULL IS NULL THEN [_TYPE] ELSE #TYPE END
Finally: I decided to go with SQL Append and following to validate/set parameter.
string paramAppend;
var bld = lstTypeSearch.SelectedItem;
if (bld != null)
{
paramAppend = "AND TT.[_TYPE] = " + lstTypeSearch.SelectedItem.ToString();
}
else
paramAppend = "";
It looks like lstTypeSearch here represents a column name (hence parameterization: not an option), so the first thing I'd say is: make sure you white-list that. Rather than trying to do everything in one go, separate the two cases:
if(string.IsNullOrEmpty(lstTypeSearch.SelectedItem))
{
// nothing to check?
}
else
{
CheckValidColumn(lstTypeSearch.SelectedItem); // throws if white-list fails
sql.Append(" AND TT.[_TYPE] = [") // should probably add table alias
.Append(lstTypeSearch.SelectedItem)
.Append("]");
}
If I have misunderstood, and this isn't a column, then just parameterize:
if(string.IsNullOrEmpty(lstTypeSearch.SelectedItem))
{
// no restriction?
}
else
{
sql.Append(" AND TT.[_TYPE] = #type");
cmd.Parameters.AddWithValue("type", lstTypeSearch.SelectedItem);
}
// ...
cmd.CommandText = sql.ToString();
First, you should work with parameters, unless want to be exposed to potential sql injection threats.
Second, if you are building the sql dynamically in the code, a better approach would be to add the sql condition only if lstTypeSearch.SelectedItem is not an empty string or null. something like that:
sSql = "your sql query";
if(!String.IsNullOrEmpty(lstTypeSearch.SelectedItem)) {
sSql += "TT.[_TYPE] = '" + lstTypeSearch.SelectedItem + "'";
}
sSql += ";"
btw, what if the SelectedItem has a string that only contains white spaces? consider replacing the String.IsNullOrEmpty to String.IsNullOrWhiteSpace.
With the edit, you should be able to replace the last line with:
AND (#Type IS NULL OR TT.[_TYPE] = #Type)
far clearer, although frankly it doesn't make for great query cache plan usage or optimization; it would still, IMO, be better to just compose the correct SQL.
As for passing in the value:
object value = string.IsNullOrEmpty(lstTypeSearch.SelectedItem)
? (object)DBNull.Value : (object)lstTypeSearch.SelectedItem;
// ...
cmd.Parameters.AddWithValue("Type", value);
If null then feed that into the case when within SQL, so it will return all the data.
I'm interpreting this to mean that if there's no value specified then return all the rows, otherwise filter by that value.
I'm assuming lstTypeSearch.SelectedItem is your value and it's a string. If not, cast it or dig out the string value.
command.CommandText =
"SELECT * FROM TT WHERE #SelectedItem IS NULL OR TT.[_TYPE] = #SelectedItem";
var selectedItem = (string) lstTypeSearch.SelectedItem;
command.Parameters.AddWithValue("#SelectedItem",
String.IsNullOrEmpty(selectedItem) ? (object) DBNull.Value : selectedItem);
using (var dataReader = command.ExecuteReader())
{
...
}
I'm diving head first into both C# and Access databases. This is all brand new to me, so I have a small test database set up to work with a small template. I'm trying to figure out why I keep getting a syntax error that is triggered by the ExecuteNonQuery() method. Any help and insight would be appreciated.
Edit: SOLVED: This is the working code for this situation. All help was greatly appreciated!
public void addToDb()
{
String first = "John";
String last = "Doe";
String testPath = GVar.TEST_FILEPATH + GVar.TEST_DATABASE;
String strCommand = "INSERT INTO ID ([First], [Last]) Values(#First, #Last)";
OleDbConnection dbTest = null;
OleDbCommand cmd = null;
try
{
dbTest = new OleDbConnection(GVar.OLE_DB_WRITE + testPath);
dbTest.Open();
cmd = new OleDbCommand(strCommand, dbTest);
cmd.Parameters.AddWithValue("#First", first);
cmd.Parameters.AddWithValue("#Last", last);
cmd.ExecuteNonQuery();
Console.WriteLine("Data Added");
}
catch (Exception ex)
{
Console.WriteLine("Db Test: " + ex.Message);
}
dbTest.Close();
}
From OleDbCommand.Parameters property
The OLE DB .NET Provider does not support named parameters for passing
parameters to an SQL statement or a stored procedure called by an
OleDbCommand when CommandType is set to Text. In this case, the
question mark (?) placeholder must be used. For example:
SELECT * FROM
Customers WHERE CustomerID = ?
Therefore, the order in which
OleDbParameter objects are added to the OleDbParameterCollection must
directly correspond to the position of the question mark placeholder
for the parameter in the command text.
I don't see anything wrong in your INSERT statement other than this.
cmd.CommandText = "INSERT INTO Identity ([First],[Last]) VALUES(?, ?)";
cmd.Parameters.AddWithValue("#First", first);
cmd.Parameters.AddWithValue("#Last", last);
cmd.ExecuteNonQuery();
In my c# application i am trying to delete a record and i am returning result of the executenonquery to check the deletion is exactly happening as below.
rowsAffected = db.ExecuteNonQuerySQL(
#"DELETE FROM relation WHERE parent_itemid = " + SourceThingId + " AND " +
" child_itemid = " + ThingId + " AND " +
" relation_typeid = " + RelationTypeId);
And the executenonquery is definesd as below,
using (SQLiteTransaction dbtrans = conn.BeginTransaction())
{
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sqlExpr;
cmd.CommandType = CommandType.Text;
ireturn = cmd.ExecuteNonQuery();
dbtrans.Commit();
}
return ireturn;
But when i am executing its not deleting and the value returns 0.The databse used is sqlite.
Do any one have idea why it happens.Please help.
Thanx in advance.
Well it certainly sounds like the record simply isn't there. You should debug this by running a SELECT * with the same query, and see whether you get any results back.
You should also stop putting your values directly into SQL, and instead use parameterized SQL. That will give a better separation of code and data, avoid SQL injection attacks, and avoid conversion issues (particularly with date/time values).