I have following function in my DataAcess class, but it is not showing any result.
My code is as follow:
public List<Products> GetProduct(string productName)
{
System.Data.DataSet ds = null;
db = DBWrapper.GetSqlClientWrapper();
db.ClearParameters();
db.AddParameter(db.MakeInParam("#ProductName", DbType.String, 30, productName));
string query = #"SELECT ProductId
FROM [Products]
WHERE Name LIKE '%#ProductName%'";
ds = db.GetDataSet(query);
db.ClearParameters();
// Rest of Code
}
I also tried:
string query = #"SELECT ProductId
FROM [Products]
WHERE Name LIKE '%"+"#ProductName"+"%'";
But it runs fine without parameterized like:
string query = #"SELECT ProductId
FROM [Products]
WHERE Name LIKE '%"+productName+"%'";
How to write this with parameterized using #ProductName???
You should use
LIKE '%' + #ProductName + '%'
instead of
LIKE '%#ProductName%'
Why? Because in query, your parameter is inside quotes. In quotes, SQL will recognize it as a string literal and never sees it as a parameter.
As an alternative, you can use your % % part in your AddParameter method as
Damien_The_Unbeliever mentioned.
Try, instead:
db.AddParameter(db.MakeInParam("#ProductName", DbType.String, 30, "%" + productName + "%"));
string query = #"SELECT ProductId
FROM [Products]
WHERE Name LIKE #ProductName";
SQL doesn't look for parameters inside of literal strings. So you can make the parameter be the entire string argument for the LIKE operator.
Rather than adding a parameter, you can also use:
string query = String.Format("Select ProductId FROM Products where Name LIKE '{0}'", productName);
Related
I'm want to refactor the following statement to change the where businessID = something to a statement where I provide a list of strings which contain all possible Ids e.g. where businessID in List. As now the query is executed in a for loop for each Id, which I'm guessing is not really performant. I can't seem to find information on how to use a List of strings as a parameter in a prepared statement.
using (SqlConnection myConnection = new SqlConnection("Data Source=.\\SERVER;Initial Catalog=DB;Integrated Security=True;TrustServerCertificate=True;User Instance=False"))
using (SqlCommand myCommand = myConnection.CreateCommand())
{
myConnection.Open();
myCommand.CommandText = "SELECT BusinessName FROM Businessess WHERE BusinessID = #Param2";
myCommand.Parameters.AddWithValue("#Param2", myParam2);
using (SqlDataReader reader = myCommand.ExecuteReader())
{
if (reader.Read())
{
string businessName = reader.GetString(reader.GetOrdinal("BusinessName"));
MessageBox.Show(businessName);
}
else
{
MessageBox.Show(string.Format("Sorry, no business found with id = {0}", myParam2));
}
}
}
You can use IN instead of equality, by adding comma separated ids in #Param2
"SELECT BusinessName FROM Businessess WHERE BusinessID IN(#Param2)";
IN
Determines whether a specified value matches any value in a subquery or a list.
As #Prescott suggested you the way to make a comma separated string from list you can have your AddWithValue like
myCommand.Parameters.AddWithValue("#Param2", String.Join(",", list));
As a side not try using stored procedure instead of inline queries, see comparison Stored procedures vs. inline SQL.
first create convert your list to comma separated string
string commaSeparatedList = yourlist.Aggregate((a, x) => a + ", " + x);
change the (=) to (In) and put the #Param between parenthesis
myCommand.CommandText = "SELECT BusinessName FROM Businessess WHERE BusinessID IN ( #Param2 )";
add the string (commaSeparatedList ) as parameter to your command
myCommand.Parameters.AddWithValue("#Param2", commaSeparatedList );
I'm using this string to update database and in this case, it works fine. It updates Znesek_nakupa in in last row:
string sqlUpd = "UPDATE Racun SET Znesek_nakupa='10' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun)";
But when I'm trying to insert variable and not just 10 it gives me error:
Error converting data type varchar to numeric.
Code example:
double totalPrice = 1.1;
string sqlUpd = "UPDATE Racun SET Znesek_nakupa='totalPrice' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun)";
How can I do this?
This problem less to do with SQL, and more to do with using strings and variables in C#.
In order to insert the value of a variable in a string in C#, you can't just place the name of the variable in the string. The string doesn't "know" that it contains a variable. Here are a couple of approaches that will work instead:
double totalPrice = 1.1;
// string concatenation
string sqlUpd =
"UPDATE Racun SET Znesek_nakupa='" +
totalPrice +
"' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun)";
// with string.Format
string sqlUpd = string.Format(
"UPDATE Racun SET Znesek_nakupa='{0}' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun)",
totalPrice);
However, the approach of just embedding a variable's value in a SQL query like this is not considered best practice as it risks SQL injection attacks. Usually you would want to use parameterised SQL queries.
A parameterised version of your query would look like this (lifting the example from the page linked to above):
SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s = "UPDATE Racun SET Znesek_nakupa='#totalPrice' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun";
SqlCommand cmd = new SqlCommand(s);
cmd.Parameters.Add("#totalPrice", totalPrice);
SqlDataReader reader = cmd.ExecuteReader();
Ok, I got it.
When I try to save variable totalPrice in database it comes to error, because C# has comma as separator. In database I have to send dot instead. So I simple replace comma with dot and now it works perfect.
So code looks like this now:
string sqlUpd = "UPDATE Racun SET Znesek_nakupa='" + Convert.ToString(totalPrice).Replace(',', '.') + "' WHERE Id_racun= (SELECT MAX(Id_racun) FROM Racun)";
I want to add a simple select statement in my C# code. Sample looks like below. The value like y in fname comes from a parameter.
//select lname from myTable where fname = 'y'
Here's what I m doing. I m obviously getting Sql Exception. How do I correct it? Thanks.
string strOrdersOrigSQL = "SELECT LastName FROM Employees";
// Concatenate the default SQL statement with the "Where" clause and add an OrderBy clause
strOrdersSQL = strOrdersOrigSQL + "where FirstName ="+ 'strFname';
You should never concat sql commands by hand. Use the class SqlCommand and add parameters
using (var cmd = new SqlCommand("SELECT LastName FROM Employees where FirstName = #firstName", conn))
{
cmd.Parameters.AddWithValue("#firstName", strFname);
var reader = cmd.ExecuteReader();
}
You dont need to worry about escaping charaters in Sql when passing from C#
Sql does it for you
all you need to do si:
string strOrdersOrigSQL = "SELECT LastName FROM Employees Where FirstName = #FirstName"
Nwo you can pass the value for #FirstName via SqlParameter this will protect you query from Sql injection
Some other problems with your query are that you are missing a space and the quotes go inside the string literal:
strOrdersSQL = strOrdersOrigSQL + " where FirstName = '"+ strFname + "'";
// ^ ^ ^
But this still won't work if the variable contains a quote character or backslash.
Instead of trying to escape the string you should use parameterized queries.
But it can be done as
string strOrdersOrigSQL = "SELECT LastName FROM Employees";
// Concatenate the default SQL statement with the "Where" clause and add an OrderBy clause
strOrdersSQL = strOrdersOrigSQL + " where FirstName ='"+ strFname + "'";
This is not proper way of doing it since it can be affected by SQL Injection. Use parameterised queries instead.
First of all, use SqlCommand. But if you choose to write direct SQL, it is OK as long as you escape your input. You should be very careful with this and know what you are doing. Else, your code presents an SQL Injection. Here is the correct code:
string strOrdersOrigSQL = "SELECT LastName FROM Employees ";
// Concatenate the default SQL statement with the "Where" clause and add an OrderBy clause
strOrdersSQL = strOrdersOrigSQL + "where FirstName = '" + strFname.Replace("'", "''") + "'";
Assuming that strFname is a variable.
I've got the following query that returns 2 records (in DataSet's query builder)
SELECT EmpID, Name, id
FROM Users
WHERE (CAST(id AS Varchar(20)) IN ('5688','5689'))
Now if I do the same query passing the parameter instead from code behind: String param = "'5688','5689'"; it returns null.
WHERE (CAST(id AS Varchar(20)) IN (#param))
I tried taking off the very first and last ', but that did not make a diffrence.
!!!id is a unique PK!!!
Anyone's got a clue?
The solution I found is quite simple, this works like a charm and there's no need for sps or other functions;
SQL:
SELECT whatever
FROM whatever
WHERE (PATINDEX('%''' + CAST(id AS Varchar(20)) + '''%', #param) > 0)
C#:
String param = "'''1234'',''4567'''";
dataTable1 = tableAdapter1.getYourValues(param);
A variable is not allowed in the IN clause.
You are expecting the values as a comma delimited string you could use the split function (user defined and non-standard) to join them with the original tables:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=326300&SiteID=1
For more information you can visit this
('5688','5689') is an array of values.
Defining String param = "'5688','5689'"; and using it as (#param) makes ('5688','5689') a string. Which wont work.
Bibhas is correct. For me this worked:
string param="'1234','4567'"; we can't use param as SQL Parameter(#param).
command = new SqlCommand("SELECT * FROM table WHERE number IN (" + param + ")", connection);
command.ExcecuteReader();
I am trying to move all of my references to variables in SQL statements to the SqlParameter class however for some reason this query fails.
string orderBy = Request.QueryString["OrderBy"];
//Fix up the get vars
if (orderBy == null)
orderBy = "name ASC";
string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY #OrderBy";
SqlCommand cmd = new SqlCommand(selectCommand, dataConnection);
cmd.Parameters.Add(new SqlParameter("#OrderBy", orderBy));
//Create the SQLDataAdapter instance
SqlDataAdapter dataCommand = new SqlDataAdapter(cmd);
//Create the DataSet instance
DataSet ds = new DataSet();
//Get data from a server and fill the DataSet
dataCommand.Fill(ds);
Here is the error
System.Data.SqlClient.SqlException: The SELECT item identified by the ORDER BY number 1 contains a variable as part of the expression identifying a column position. Variables are only allowed when ordering by an expression referencing a column name.
It fails on this line.
dataCommand.Fill(ds);
You really have three options.
1) Use a dataview to order the result set
2) If you know the columns that can be ordered you can test for the string and then use then select the order. e.g.
For example this will work
DECLARE #orderby varchar(255)
SET #orderby = 'Name ASC'
SELECT [Your Column here ]FROM sys.tables
ORDER BY
case WHEN #orderby = 'Name ASC' Then name ELSE null END ASC,
case WHEN #orderby = 'Name DESC' Then name ELSE null END DESC,
CASE WHEN #orderby = 'Object_id ASC' then object_id ELSE null END ASC,
CASE WHEN #orderby = 'Object_id DESC' then object_id ELSE null END DESC
3) The final option is to do the same as #2 but in your C# code. Just be sure you don't just tack on the ORDER BY clause from user input because that will be vunerable to SQL injection.
This is safe because the OrderBy Url parameter "Name Desc; DROP table Users"will simply be ignored
string SafeOrderBy = "";
string orderBy = Request.QueryString["OrderBy"];
//Fix up the get vars
if (orderBy == null)
orderBy = "name ASC";
if (orderby == "name Desc")
{
SafeOrderBy == "name Desc"
}
string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY "
selectCommand += SafeOrderBy ;
Using SqlCommand is the way to prevent from sql injection. Your way of changing of the order by is the same as using sql injection in this context so it shouldnt be allowed - params are used as the constants, can't be used as column or table names.
u dont have to concatenate content of sortBy just use it as enum and depending on its value concatenate something you're sure that is safe. Like this:
If(orderBy == "some_column")
{
selectColumn += "someColumn";
}
...
I ran in to the same problem as you, however the listed solutions could not be used since my possible sort column was one of the properties of a model and that would mean way too many if-statements if the model is big.
My solution to this related problem is to use Reflection. Something like:
class MyModel {
public string MyField1 { get; set; }
public string MyField2 { get; set; }
// ...
}
//...
using System.Reflection;
// sortBy = "MyField1"
// sortDirection = "Asc";
var sql = "SELECT FROM foo WHERE bar=baz ORDER BY ";
foreach (var prop in typeof(MyModel).GetProperties())
{
if (sortBy.Equals(prop.Name))
{
sql += (prop.Name + (sortDirection.Value.Equals("Asc") ? " ASC" : " DESC"));
break;
}
}
The benefit to this solution is that no matter how my model changes, this code will support sorting by any of its properties and thus doesn't need to be changed as well.
I found an example how to do this here
you can define different sort orders in a CASE-structure and execute them appropriately to your variable value:
SELECT CompanyName,
ContactName,
ContactTitle
FROM Customers
ORDER BY CASE WHEN #SortOrder = 1 THEN CompanyName
WHEN #SortOrder = 2 THEN ContactName
ELSE ContactTitle
I didn't test it myself but it could work. You can give it a try. An obvious disadvantage is that you have to code all the order-by statements.
You're just concatenating strings. A simpler approach would be:
string orderBy = "name ASC";
string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY " + orderBy;
I'm assuming you're doing this at all because you're letting the caller decide sort field/direction, hence orderBy separated.
Parameters, as the error message sort of obliquely hints at, would be used in a WHERE clause, e.g. WHERE someColumn = #someValue etc.