I'm trying to build a dynamic sql query to update a table in SQL Server, like this:
string alan = "SaticiKodu";
DynamicParameters paramStSabit = new DynamicParameters();
string sqlSabit = "UPTADE TBLSTSABIT SET ";
if (alan == "SaticiKodu")
{
sqlSabit += " SATICI_KODU = #SaticiKodu ,";
paramStSabit.Add("SaticiKodu", _msk.SaticiKodu);//_msk.SaticiKodu comes from List<T> in foreach loop
}
if (sqlSabit.Contains("=")) // here I check if I have any column update with '='
{
sqlSabit += "WHERE STOK_KODU = #StokKodu";
paramStSabit.Add("StokKodu", _msk.StokKodu);
sqlSabit= sqlSabit.Replace(",WHERE", " WHERE");
db.Execute(sqlSabit, paramStSabit, transaction: _transaction, commandType: CommandType.Text);
}
I have a list of objects, it has lots of properties but to make example short, here I write only StokKodu and StokAdi. This code throws an error
Incorrect syntax at '='
I think this code should work with Dapper.
How can I make this code work, where is my mistake? Thanks for the help from now.
All i do is changing
string sqlSabit
to
StringBuilder sqlSabit
and instead of join strings with +=, i used sqlSabit.Append(), now code is working. And i tested with string, integer and float typed columns/parameters, no problem.
But couldn't understand why StringBuilder solves the problem.
Related
I have a list of items with different ids which represent a SQL table's PK values.
Is there any way to build an efficient and safe statement?
Since now I've always prepared a string representing the statement and build it as I traversed the list via a foreach loop.
Here's an example of what I'm doing:
string update = "UPDATE table SET column = 0 WHERE";
foreach (Line l in list)
{
update += " id = " + l.Id + " OR";
}
// To remove last OR
update.Remove(update.Length - 3);
MySqlHelper.ExecuteNonQuery("myConnectionString", update);
Which feels very unsafe and looks very ugly.
Is there a better way for this?
So yeah, in SQL you've got the 'IN' keyword which allows you to specify a set of values.
This should accomplish what you would like (syntax might be iffy, but the idea is there)
var ids = string.Join(',', list.Select(x => x.Id))
string update = $"UPDATE table SET column = 0 WHERE id IN ({ids})";
MySqlHelper.ExecuteNonQuery("myConnectionString", update);
However, the way you're performing your SQL can be considered dangerous (you should be fine as this just looks like ids from a DB, who knows, better to be safe than sorry). Here you're passing parameters straight into your query string, which is a potential risk to SQL injection which is very dangerous. There are ways around this, and using the inbuilt .NET 'SqlCommand' object
https://www.w3schools.com/sql/sql_injection.asp
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand?view=dotnet-plat-ext-6.0
It would be more efficient to use IN operator:
string update = "UPDATE table SET column = 0 WHERE id IN (";
foreach (Line l in list)
{
update += l.Id + ",";
}
// To remove last comma
update.Remove(update.Length - 1);
// To insert closing bracket
update += ")";
If using .NET Core Framework, see the following library which creates parameters for a WHERE IN. The library is a port from VB.NET which I wrote in Framework 4.7 years ago. Clone the repository, get SqlCoreUtilityLibrary project for creating statements.
Setup.
public void UpdateExample()
{
var identifiers = new List<int>() { 1, 3,20, 2, 45 };
var (actual, exposed) = DataOperations.UpdateExample(
"UPDATE table SET column = 0 WHERE id IN", identifiers);
Console.WriteLine(actual);
Console.WriteLine(exposed);
}
Just enough code to create the parameterizing SQL statement. Note ActualCommandText method is included for development, not for production as it reveals actual values for parameters.
public static (string actual, string exposed) UpdateExample(string commandText, List<int> identifiers)
{
using var cn = new SqlConnection() { ConnectionString = GetSqlConnection() };
using var cmd = new SqlCommand() { Connection = cn };
cmd.CommandText = SqlWhereInParamBuilder.BuildInClause(commandText + " ({0})", "p", identifiers);
cmd.AddParamsToCommand("p", identifiers);
return (cmd.CommandText, cmd.ActualCommandText());
}
For a real app all code would be done in the method above rather than returning the two strings.
Results
UPDATE table SET column = 0 WHERE id IN (#p0,#p1,#p2,#p3,#p4)
UPDATE table SET column = 0 WHERE id IN (1,3,20,2,45)
I want to be able to take content from a web page text box and pass it to a SQL Server stored proc that will perform a search on a full-text catalog.
In C#, we are using a SQL Command object to setup parameters needed to call on a stored procedure: one of the parameters contains the query text:
public List<SearchItems> mySearchFunction(string query.....)
{
blah//....
SqlParameter paramQry = new SqlParameter();
paramQry.ParameterName = "#qry";
paramQry.SqlDbType = SqlDbType.NVarChar;
paramQry.Direction = ParameterDirection.Input;
paramQry.Value = query;
cmd.Parameters.Add(paramQry);
......
}
On the SQL side of things, the stored proc will use the query text as:
SELECT RequiredColumns
FROM tableName
WHERE CONTAINS((ourTableField), #qry).....
This is fine for simple (one-word) search terms.
How do I convert/pass multi-word or phrases in C# to work in SQL?
For example, if a user enters "Barack Obama" in the text field, we would want to setup the #qry value passed to the SP to look this in the query:
WHERE CONTAINS((ourTableField),'"Barack" AND "Obama"')
Do I need to do some sort of string construction in C#? I have tried this by trying to insert AND and quote literals, but the issue of escaping single and double quotes is tripping me up, and I am concerned this is not a sensible or safe way to continue trying.
I have been trying to build this in C# using a StringBuilder object, along the lines of:
List<string> queryParts = query.Split(' ').ToList();
string queryVal = string.Empty;
if (queryParts != null & queryParts.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.Append("'");
foreach (string searchPart in queryParts)
{
sb.Append("\"" + searchPart + "\"" + "AND");
}
//bit hacky, removing trailing AND
sb.Append("'");
sb.Replace("AND'", string.Empty);
sb.Append("'");
queryVal = sb.ToString();
return queryVal
Then assign paramQry.Value = queryVal;
However this results in escaping - slashes etc. being returned. I am sure this is not just a case of Visual Studio rendering these characters in the debugger -the exception that comes back is SQLException.
I have seen similar posts where it is mentioned that the Parameter object can handle escaping, but I cannot see how this works or find any clear examples that may help.
If this is not feasible, does this mean doing some sort of string manipulation in SQL?
This type of solution is new to me, so TIA for advice offered.
You can use StringBuilder to construct your sentence by adding and to every empty space, and build a sentence out of the content of the textbox
I'm trying to understand why in C# if you have a sql string why you would have to put tick (') marks in the following where clause in order for this to work. Could someone please explain the reasoning behind this?
where ProgramServer='" + machineName.ToString() + "' and Active=1;
You can avoid those tick (') marks and use Parameters, They will also save you from SQL Injection.
The reason you see those ticks are because SQL expects string type values to be enclosed in single ticks.
What you're seeing is a dynamically built SQL query in the code. When querying based on a string value, the string must be wrapped in single quotes. The final SQL string would look something like:
select * from someTable where ProgramServer = 'YourMachineName' and Active = 1;
Unfortunately, that is far from the best way to do things. You should be using parameterized queries instead:
var query = "select * from someTable where ProgramServer = #machineName and Active = 1;";
using(var conn = new SqlConnection(connString))
{
var command = new SqlCommand(query, conn);
command.Parameters.Add("machineName", machineName.ToString());
// Execute and get the results
}
When I try to execute this, I get an exception saying the syntax is incorrect?
string sql= string.Format(#"SELECT valueA
FROM tableA
WHERE columnA = #columnValueA");
var parameters = new MySqlParameter[1];
parameters[0] = new MySqlParameter("#columnValueA", string.Format("{0}","abc"));
foreach (var mySqlParameter in parameters)
{
cmd.Parameters.AddWithValue(mySqlParameter.ParameterName, mySqlParameter.Value);
}
//later I execute, it tells me the syntax is incorrect
-- I am trying to execute something on the database similar to below
SELECT valueA
FROM tableA
WHERE columnA = "abc"
do you need # in the MySqlParameter string? I would imagine you could do without it?
My query is correct, essentially, what was happening nested deeply within the code was it was appending an extra ) which was rendering the query syntax incorrect.
I'm trying to do a basic insert statement using a parameterized query. My problem is whatever the syntax I'm using it seems like the query is being done with all parameters set to null instead of their appropriate values (unless I hard-code the value in the command text).
Here is the code :
m_Command.CommandText = "INSERT INTO " + s_TracesTabelName + " (DateTimeTraceCreated,
Span, CenterFrequency, Data, DateTimeTestStarted) VALUES (#traceTime, #Span,
#CenterFrequency, #Data, #testTime)";
//just trying another syntax
MySqlParameter param = m_Command.CreateParameter();
param.MySqlDbType = MySqlDbType.Datetime;
param.ParameterName = "#traceTime";
param.Value = trace.TimeCreated;
m_Command.Parameters.Add(param);
//m_Command.Parameters.Add("#traceTime",MySqlDbType.Datetime,8,"DateTimeTraceCreated");
//m_Command.Parameters["#traceTime"].Value = trace.TimeCreated;
m_Command.Parameters.Add("#Span", trace.Span);
m_Command.Parameters.Add("#CenterFrequency", trace.CenterFrequency);
m_Command.Parameters.Add("#Data", data);
m_Command.Parameters.Add("#testTime", testStarted);
try
{
m_Connection.Open();
m_Command.ExecuteNonQuery();
}
catch(Exception e)
{
Console.WriteLine("Error Connecting to Database\n");
//errorlog
}
finally
{
m_Connection.Close();
}
The three different syntaxes lead me to null parameters' value.
ps : I've seen many people using command.Parameters.AddWithValue() method, but I seem to just don't have it.
Kind regards,
Ben
Could be your version of mysql ADO provider?
C# MySqlParameter problem
Try with ? instead of #