I want to save formatted text into a table, and i use this nice rich text editor that outputs HTML. When I run it i get:
There was an error parsing the query. [ Token line number = 1,Token
line offset = 31,Token in error = < ]
My command looks like:
new SqlCeCommand("UPDATE Bio SET text = " + form["textbox"].Replace("\"", """) + " WHERE id = " + ViewBag.Id, conn)
But I guess it does not like <>, what do I need to replace? Do the same with the quote as with the <>? Any function that escapes it all?
See here for an example of passing the text you want to insert as a parameter:
http://msdn.microsoft.com/en-us/library/system.data.sqlserverce.sqlcecommand.parameters(v=vs.100).aspx
As recommended by MattD - here is example code. Note that I did not actually run this, if there is a syntax issue, leave a note and I'll fix it. This should get you 99% of the way in any case.
Also note: it is ALWAYS a good idea to use parameters this way, rather than appending literal text into a sql query. This eliminates the possibility of a SQL injection error or hack, where someone might maliciously enter text that finishes your SQL and then adds their own SQL that will also get executed.
SqlCeCommand command = new SqlCeCommand("UPDATE Bio SET text = #htmlText WHERE id = #id", conn);
SqlCeParameter param;
// NOTE:
// For optimal performance, make sure you always set the parameter
// type and the maximum size - this is especially important for non-fixed
// types such as NVARCHAR or NTEXT; In case of named parameters,
// SqlCeParameter instances do not need to be added to the collection
// in the order specified in the query; If however you use ? as parameter
// specifiers, then you do need to add the parameters in the correct order
//
param = new SqlCeParameter("#id", SqlDbType.Int);
command.Parameters.Add(param);
param = new SqlCeParameter("#htmlText", SqlDbType.NVarChar, -1);
command.Prepare();
//Set the values and the length of the string parameter
command.Parameters[0].Value = ViewBag.Id;
command.Parameters[1].Value = form["textbox"];
command.Parameters[1].Size = form["textbox"].Length;
// Execute the SQL statement
//
command.ExecuteNonQuery();
Related
SqlCommand command = new SqlCommand("UPDATE qcCheckList SET reviewed = #0, errorLevel = #1, comment = #2 WHERE guid = #3 and itemId = #4", connection);
command.Parameters.AddWithValue("0", cli.reviewed.Checked);
int errorLevel = 0;
if (cli.error.Text == "Level 1")
errorLevel = 1;
else if (cli.error.Text == "Level 2")
errorLevel = 2;
else if (cli.error.Text == "Level 3")
errorLevel = 3;
command.Parameters.AddWithValue("1", errorLevel);
command.Parameters.AddWithValue("2", cli.comments.Text);
command.Parameters.AddWithValue("3", guid);
command.Parameters.AddWithValue("4", cli.itemId);
command.ExecuteNonQuery();
Console.WriteLine(command.CommandText);
When i run this code it doesn't look like my sql command's parameters are being replaced by their actual values. I want to be able to see their values when the command is compiled so i can see if the correct command is being sent. Any ideas?
Answer is based on my assumption that you are expecting the query statement (string) to change. That assumption is based on your wording as well as the last sentence in your code statement.
Console.WriteLine(command.CommandText);
The query text is not altered, ie. the parameters in the query text are not replaced with the assigned parameter values. The parameters, and their values, are sent with the query text to the DBMS for execution. In Sql Server you can see this if you were to profile the Sql Server Instance using Profiler.
As a side note I do not recommend you use AddWithValue. See also Can we stop using AddWithValue() already?. Instead just use Add. Also you should give meaningful names to your parameters, like "#errorLevel", when you are able to, it makes debugging easier.
command.Parameters.Add("#errorLevel", SqlDbType.Int).Value = errorLevel;
It is not necessary to prefix the parameter names with "#" when calling Add as it will be done for by the method if you did not. It is considered good practice though but that is a matter of opinion.
When you are assigning value to the parameters, command string will not change. To see actual values of the parameters you can get values after they are being assigned
foreach (SqlParameter item in command.Parameters)
{
Console.WriteLine(item.ParameterName + "=" + item.Value);
}
This will display actual values
dont use # numbers, but named.. such as #parmReview, #parmError, etc... then the NAMED values are in your
command.Parameters.AddWithValue( "parmReview", cli.reviewed.Checked)
command.Parameters.AddWithValue("parmError", errorLevel);
etc.
I have the following code:
/*
// it works
cmd_oper = "UPDATE [Model Elements] SET [Record Status] = \"Disabled\" WHERE [Index] = #db_idx";
/*/
// it doesn't work
cmd_oper = "UPDATE [Model Elements] SET [Record Status] = #stat WHERE [Index] = #db_idx";
//*/
using( OleDbCommand cmd = new OleDbCommand( cmd_oper, svr_conn ) )
{
cmd.Parameters.Add( "#db_idx", OleDbType.Integer ).Value = 2;
//cmd.Parameters.Add( "#stat", OleDbType.VarChar ).Value = "Disabled";
cmd.Parameters.AddWithValue( "#stat", "Disabled" );
cmd.ExecuteNonQuery();
}
With the second variant of cmd_oper (the one not commented in the beginning of the code) I get "Data type mismatch in criteria expression". The other one works. The type of Record Status column is set in database as Short Text. I know there are many posts related to this error on StackOverflow but I couldn't find an exact fit. Thanks.
The fine manual, https://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters(v=vs.110).aspx has the following to say about parameters
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.
Ergo, I think you need your code to be like:
cmd_oper = "UPDATE [Model Elements] SET [Record Status] = ? WHERE [Index] = ?";
using( OleDbCommand cmd = new OleDbCommand( cmd_oper, svr_conn ) )
{
cmd.Parameters.AddWithValue( "anything-name-doesnt-matter", "Disabled" );
cmd.Parameters.Add( "its-position-that-matters", OleDbType.Integer ).Value = 2;
cmd.ExecuteNonQuery();
}
For what it's worth, you should probably name your parameters sensibly (I named them silly above to demonstrate that the name is irrelevant) because the idea is that once prepared, you can execute a statement many times just changing the parameters:
cmd.Parameters["its-position-that-matters"].Value = 3;
cmd.ExecuteNonQuery();
cmd.Parameters["its-position-that-matters"].Value = 4;
cmd.ExecuteNonQuery();
cmd.Parameters["its-position-that-matters"].Value = 5;
cmd.ExecuteNonQuery();
cmd.Parameters["its-position-that-matters"].Value = 6;
cmd.ExecuteNonQuery();
Here i've run the update for index values 3, 4, 5 and 6 too, just by changing the parameter value and re-running. It would hence have been better of me to choose a sensible name for the "index" parameter, to make the code more readable
Steve, in his comment, has noted he believes that you can put named parameters in the query, but the names are ignored (they're essentially treated as ? marks anyway) so you'll still need to add the parameter values in the same order as the placeholders appear. If you have repeated a placeholder in a query, you'll have to repeat-add it to the parameters collection. I've no comment on the accuracy of steve's assertion; I've always used ?
Ultimately, this is all good evidence that really you should get into learning to use a data access library like Entity Framework, and stop writing SQL strings in your button click event handlers - it's not a good way to code. If you'd used EF from the outset, you'd never even have hit this problem. Good on you for using parameterised queries though. Now go check out EF and leave this '90s donkey-way of doing data access behind :)
I am stuck at one problem and I just can't solve this.
I get this Error:
Error Message
That's the relevant table
The Code:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = " + #departmentCB.Text;
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#nextMaintainance", nextMaintainanceDT.Value);
command.ExecuteNonQuery();
The weird thing I don't understand is that a similar code works just fine without any error in my project:
query = "UPDATE LDV SET received = #received, department = #department WHERE Id =" + #idTxt.Text;
command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#received", inDT.Value);
command.Parameters.AddWithValue("#department", departmentCb.Text);
command.ExecuteNonQuery();
MessageBox.Show("Lungenautomat wurde aktualisiert");
If relevant, my connection string:
connectionString = ConfigurationManager.ConnectionStrings["SCBA_Manager_0._1.Properties.Settings.SCBAmanagerConnectionString"].ConnectionString;
I really hope you can help me :(
Thank you!
The department column is a text column, so comparing it to a value means the value should be wrapped in quotes.
// This fix is not the recommended approach, see the explanation after this code block
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = '" + departmentCB.Text + "'";
// ^--------------------------^------ single quote added to wrap the value returned by departmentCB.Text
On the other hand, this error does not occur in your second example, because there you're correctly using the Parameters.AddWithValue() method to add the value for the #department parameter, and because id is a numeric column, so it doesn't require the value wrapped in quotes.
However, while the code shown above does the job, it is not the right way of doing the job. The correct way is to used parameters for all values to be injected into a query. The queries you've shown above are already correctly using parameters for some values (e.g. nextMaintenance in the first query, received and department in the second), but are incorrectly doing string concatenation for other values (e.g. department in the first query, id in the second).
Usage of Parameterized SQL
The benefit of using parameterized SQL is that it automatically takes care of adding quotes, prevents SQL injection, etc.
Therefore, its best to change your first code block to:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = #department";
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#department", departmentCb.Text);
command.Parameters.AddWithValue("#nextMaintainance", nextMaintainanceDT.Value);
command.ExecuteNonQuery();
Notice how the string query is a single string without any messy concatenation, and that it contains two parameters #nextMaintenance and #department? And how the values for those parameters are correctly injected using Parameters.AddWithValue() in the following lines?
Your second code block can be similarly improved by using a parameter for the Id column.
query = "UPDATE LDV SET received = #received, department = #department WHERE Id = #Id ";
command.Parameters.AddWithValue("#Id", idTxt.Text);
Further Information
Do read up about SQL injection ( https://technet.microsoft.com/en-us/library/ms161953(v=sql.105).aspx ) to see how using string concatenation like your original code can lead to various security issues, and why parameterized queries are the preferred way of injecting dynamic values into SQL queries.
You can read up more about parameterized queries here: https://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx
In your first example, the WHERE clause evaluates to
WHERE department = Kasseedorf
wheras it should be
WHERE department = 'Kasseedorf'
So the line should be
string query = "UPDATE CAC SET nextMaintainance = #nextMaintainance WHERE department = '" + #departmentCB.Text +"'";
It works in the second example, because id is an integer and doesn't neet quotes.
Using C# on VS13 with a connected Access database and am receiving the error "No value given for one or more required parameters" when executing certain SQL.
Here is my code. Thanks for your time!
// ID accessors for an itemLine object
public void setID(string Value) { ID = Value; }
public string getID() { return ID; }
...
// Code snippet where error originates
foreach (CartItem itemLine in parBasket)
{
cmd.CommandText = "SELECT Instock FROM tblProducts WHERE ProductID = " + itemLine.getID() + "";
OleDbDataReader reader = cmd.ExecuteReader();
reader.Read();
int stock = Convert.ToInt32(reader["Instock"]);
stock = stock - itemLine.getQuanity();
reader.Close(); //Close the reader
cmd.CommandText = "UPDATE tblProducts SET InStock =" + stock + " WHERE ProductID = " + itemLine.getID() + "";
updated = updated + cmd.ExecuteNonQuery();
}
cn.Close();
return updated;
}
If CartItem.getID() returns an integer, not a string, then you need to remove the single quotes around it in the SELECT statement you are building.
Even better - read up on using SqlParameter and use this when building queries like this, as it helps avoid this sort of error, and also prevents SQL injection attacks, if any of the parameter data comes directly from user input.
To fix those errors yourself, you should:
Run with the debugger;
When the SQL command throws an exception the debugger should break (at least if it's unhandled. If you catch it, the debugger may still break but you have to tweak its config to do so);
Use a Watch or something to look at the CommandText of your SqlCommand (i.e. the SQL text that actually gets executed).
This should make pretty obvious what is wrong.
Now using my Crystal ball rather than a debugger, I think your problem is that getId() returns a string (per your comment on the question) and you end up with something like: WHERE ProductID = FortyTwo in both the first and second SQL queries.
The bad solution to this would be to enclose the string in quotes: WHERE ProductID = 'FortyTwo' but you should be careful that your ID doesn't contain a quote itself (which you should escape).
The good solution is to use a SQL parameter. Assuming SQL Server syntax: WHERE ProductID = #id and cmd.Parameters.AddWithValue("id", item.GetId()). (Note: you use the same command repeatedly, you should not add the parameter repeatedly. Rather, add it once and then change its value at each iteration.)
Does anyone know how can I read the output variable from .net c#?
Example:
If I have the following stored proc which will return the output variables (#customer_id, #customer_name, #customer_address, #customer_age) instead of the select variable, how can I read the output variable with the following?
mySqlCommand.CommandText = "EXEC app_customers #name=" + sName.Text;
mySqlConnection.Open();
SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
while (mySqlDataReader.Read())
{
}
When the result is a single value (or if you're just interested in the first value in the first column), use the method ExecuteScalar.
It returns an object, simply cast it to the expected type.
int id = (int)mySqlCommand.ExecuteScalar();
Note: the way you're invoking a procedure is not the normal way to do it. Set the command to reference the stored procedure, then add appropriate parameters to the command.Parameters collection. Invoking the procedure using "exec ..." is not a best practice and may even leave you vulnerable. If you need more info on executing such a call, start here.
Edit:
If it is truly an output parameter you need to capture (I believe I misread your question), then the above paragraph is even more applicable. Consider this approach:
mySqlCommand.CommandText = "app_customers";
mySqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
mySqlCommand.Parameters.AddWithValue("#name", theValue);
var customerIdParam = mySqlCommand.Parameters.Add("#customer_id", System.Data.SqlDbType.Int);
customerIdParam.Direction = System.Data.ParameterDirection.Output;
// add more parameters, setting direction as appropriate
mySqlCommand.ExecuteNonQuery();
int customerId = (int)customerIdParam.Value;
// read additional outputs