C#: How to pass parmeterize values to System.Data.Entity.SqlSquery - c#

I'm going to execute SQL query directly on database.
I've define connection to my database using:
System.Data.Entity.DbContext rawDbContext = new DbContext(connectionString);
I don't want to insert parameters directly to query string to avoid SQL Injection so I want to set parametrized values for my SQL query this way:
string sqlCommandString =
"IF EXISTS(select* from #MappingTableName where " + Environment.NewLine +
"BranchID= #PrimaryKeyID and " + Environment.NewLine +
"BranchNo = #BranchNo and " + Environment.NewLine +
"TableName = #TableName and " + Environment.NewLine +
"BranchSchema = #SchemaNameInBranch and " + Environment.NewLine +
"TableID = #TableID) " + Environment.NewLine +
" select 1" + Environment.NewLine +
"ELSE " + Environment.NewLine +
"select 0 " + Environment.NewLine;
SqlParameter parameterMappingTableName = new SqlParameter("#MappingTableName", vipMappingTableName);
SqlParameter parameterSchemaNameInBranch = new SqlParameter("#SchemaNameInBranch", schemaName);
SqlParameter parameterPrimaryKeyInBranch = new SqlParameter("#PrimaryKeyID", primaryNodeId);
SqlParameter parameterBranchNo = new SqlParameter("#BranchNo", branchNo);
SqlParameter parameterTableId = new SqlParameter("#TableID", tableId);
SqlParameter parameterTableName = new SqlParameter("#TableName", tableName);
DbRawSqlQuery<int> result = rawDbContext.Database.SqlQuery<int>(sqlCommandString,
new[] {
parameterMappingTableName,
parameterSchemaNameInBranch,
parameterPrimaryKeyInBranch,
parameterBranchNo,
parameterTableId,
parameterTableName
});
int finalResult = result.Single();
Running this query leads to excpetion "Must declare the table variable \"#MappingTableName\"."
How can I fix this?

Check this from Microsoft forums
Database objects (tables, stored procedures or any other objects)
cannot be passed as parameters. Only actual values for columns or
variables can be parameters. You need to build your SQL statement
dynamically in this case
Which basically means that you have to provide and/or build the table name, under the danger that this can be compromised.
How to mitigate the risk. Declare a set of probable table name and do an exact match.
Then build your query with text concatenation. This is something that can't be done with parameters cause you can't expect the possible values, but can be done with tables because they are only so many. Be carefull to use Equals instead of Contains in your list of names.

Related

Error : in my query i am using multiple variables in c#

i am not getting what is the issue in the query probably i am not following the correct way to put the string and char sign , i am inserting the data in c# to local host with where clause please check the query and Error i am getting
Here is the query
String insertQuery = "insert into exam_add (id,session_id,Title,From_date,To_date,class_id,is_Post,is_Lock) select '"+id+ ",s.session,'" + title.Text+",'"+ from.Value.Date.ToString("yyyy-MM-dd")+",'"+to.Value.Date.ToString("yyyy-MM-dd")+ ", c.class_name,'"+x+",'"+x+" from year_session s, classes c where s.id = '1' and c.id='" + cls + "'";
Exception image
here the image for exception i am getting after run this query
On your ...'"+x+"... you forgot to close the single quotes. You open them but you never close them after you add the X variable to your query. All SQL is seeing is "'0," which is invalid syntax.
I recommend use SQLparameters to avoid sql injection but your error is you forgot to close the single quotes it shoud be like this '"+cls + "'
String insertQuery = "insert into exam_add (id,session_id,Title,From_date,To_date,class_id,is_Post,is_Lock) select '" + id + "','"+s.session+"','" + title.Text + "','" + from.Value.Date.ToString("yyyy-MM-dd") + "','" + to.Value.Date.ToString("yyyy-MM-dd")+"' , '"+c.class_name+"','" + x + "','" + x + "' from year_session s, classes c where s.id = '1' and c.id='" + cls + "'";
I don't know why you need that on select columns. and you provided insufficient information and code on your question.

Does TryParse protect against sql injection?

I have an SQL request where I need to concatenate data into the request:
if (dataChoosen != "randomValue")
{
sCondition = " WHERE RandomField = '" + dataChoosen + "' ";
}
cd.CommandText = "SELECT xData FROM table " + sCondition + "GROUP BY xxx";
As I need to concatenate the condition, I don't think I can use a prepared request?
Also, I already tryparse the 'dataChoosed' value because it comes from a textbox and I need an integer. So is the the tryparse enough to prevent SQL injection?
I would just use parameters, there's no reason not to.
if (dataChoosed != "randomValue")
{
sCondition = " WHERE RandomField = #dataChoosed ";
}
cd.CommandText = "SELECT xData FROM table " + sCondition + "GROUP BY xxx";
cd.Parameters.Add("#dataChoosed", SqlDbType.VarChar).Value = dateChoosed;
No, you are not on the safe side. Even if dataChoosed is an innocent integer value, bad boys can hurt you with, say, negative value format:
// It's good old "-1", with a bit strange format
// (let use "delete from table commit;" as an injection)
string dataChoosed = "1'; delete from table commit; --1";
// A little hack: let "-" sign be...
CultureInfo hacked = new CultureInfo("en-US");
hacked.NumberFormat.NegativeSign = "1'; delete from table commit; --";
Thread.CurrentThread.CurrentCulture = hacked;
if (dataChoosed != "randomValue")
{
int v;
// since "1'; delete from table commit; --1" is of correct fotmat it will be parsed
if (int.TryParse(dataChoosed, out v))
sCondition = " WHERE RandomField = '" + dataChoosed + "' ";
}
cd.CommandText = "SELECT xData FROM table " + sCondition + "GROUP BY xxx";
And, woe! Where's my table? The command text will be
SELECT xData FROM table = '1'; delete from table commit; --1'GROUP BY xxx
which is efficently two queries:
SELECT xData FROM table = '1'; -- the innocent one
delete from table commit; -- an arbitrary query from the attacker
(I've removed commented out --1'GROUP BY xxx fragment)
Please, use parameters, do not tempt us. Please, notice, that you don't want to change code: all you have to do is to change the Regional Settings in your Windows.
Does [BLANK] protect against sql injection?
Unless [BLANK] is 'parameters' the answer is always no.

Using parameterized SQL LIKE Statements

I'm trying to parameterize my SQL Statements but I'm having some trouble with the LIKE statement. I tried different solutions but nothing works. My code:
sqlCmd = new SqlCommand("SELECT " + form1.cusId.Text + "," + form1.cusName.Text" FROM " + form1.getTable() + " WHERE " + form1.getCusId() + " LIKE #filterCustomers", connection);
sqlCmd.Parameters.AddWithValue("#filterCustomers", form1.filterCus().Trim() + "%");
I'm getting
"Must declare the scalar variable #filterCustomers".
Why ist that happening? Since this is th common solution...
What if you try
sqlCmd.Parameters.Add("#filterCustomers",SqlDbType.VarChar,8).Value = form1.filterCus().Trim() + "%";
Instead of:
sqlCmd.Parameters.AddWithValue("#filterCustomers", form1.filterCus().Trim() + "%");
You can change the.VarChar for what you data type is and the 8 for the required max field lenght, or remove the ,8 completely for no limit in the parameter lenght
you need to put your string inside single quotes ':
...+" LIKE '"+ form1.filterCus().Trim()+"%'", connection);
if you don't worry about SQL INJECTION
EDIT: you can also use dynamic sql:
sqlCmd = new SqlCommand("EXEC ('SELECT..... WHERE FIELD LIKE ''' + #filterCustomers + '%''')", connection);
sqlCmd.Parameters.AddWithValue("#filterCustomers", form1.filterCus().Trim() + "%");

How do I pass guid in parameterised query?

My current best code is:
string delNonQuery = "DELETE FROM " + Settings.DataSource + " WHERE #keycolumn=#keyuid";
SqlCommand cmd = new SqlCommand(delNonQuery,readerConn);
SqlParameter kc = new SqlParameter("keycolumn", SqlDbType.VarChar);
SqlParameter key = new SqlParameter("keyuid", SqlDbType.VarChar);
cmd.Parameters.Add(kc).Value = Settings.KeyColumn;
cmd.Parameters.Add(key).Value = Page.Request["key"].ToString().Trim();
readerConn.Open();
cmd.ExecuteScalar();
readerConn.Close();
This executes but affects a whopping zero rows. If I change the SqlDbType on keyuid to UniqueIdentifier it just ends up with me getting a dozen variations on "failed to convert character string into uniqueidentifier". I have to use a parameterized query for data cleanliness, I'm just really stuck as to how...
You can't specify a parameter for a column name - you need to concatenate it the same way you do for the table name.
This:
"DELETE FROM " + Settings.DataSource + " WHERE #keycolumn=#keyuid"
Should change to:
"DELETE FROM " + Settings.DataSource + " WHERE " + Settings.KeyColumn + " =#keyuid"
Though I would probably write it as:
string delNonQuery = string.Format("DELETE FROM {0} WHERE {1} = #keyuid",
Settings.DataSource,
Settings.KeyColumn);
For completeness sake, I will mention that this is open to SQL injection. You need to make sure your Settings values are clean.
I don't think you can parameterise the column name ("keycolumn")
Try this:
string delNonQuery = string.Format("DELETE FROM " + Settings.DataSource + " WHERE {0}=#keyuid", Settings.KeyColumn);
SqlCommand cmd = new SqlCommand(delNonQuery,readerConn);
SqlParameter key = new SqlParameter("keyuid", SqlDbType.VarChar);
cmd.Parameters.Add(key).Value = Page.Request["key"].ToString().Trim();
readerConn.Open();
cmd.ExecuteScalar();
readerConn.Close();
Usual warnings apply regarding concatanating strings to build SQL; this is likely a security risk.
The best method might be to encapsulate your SQL in a stored procedure, pass the column name and value as parameters and then execute using dynamic SQL.
You need to convert the string to GUID:
Relevant Lines:
SqlParameter key = new SqlParameter("keyuid", SqlDbType.UniqueIdentifier);
...
cmd.Parameters.Add(key).Value = new Guid(Page.Request["key"].ToString().Trim());
Which only solves the GUID/UniqueIdentifer issue

Using items from List<string> in SQL query

Ok, I have a list that consists of a bunch of values from a sql query, that part works fine. What I want to do is use the items in that list to tell another query what to look for. So, what it is saying is that, it should return all columns from CMMReports where PartNumber is like %listItem1..2...3%, Any advice?
List<string> ImportedParts = GetImportedPartNumbers();
string query = "SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') AND (FilePath NOT LIKE '%js91162%') AND PartNumber LIKE %" + ImportedParts + "% ORDER BY CreatedOn DESC;";
Not that I condone this as you should be using parameterized queries. However, this should work:
StringBuilder partNumbers = new StringBuilder();
foreach (string queryValue in ImportedParts)
{
string q = "PartNumber LIKE '%" + queryValue + "%'";
if (string.IsNullOrEmpty(partNumbers.ToString())
{
partNumbers.Append(q);
}
else
{
partNumbers.Append(" OR " + q);
}
}
string query = string.Format("SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') " +
"AND (FilePath NOT LIKE '%js91162%') AND ({0}) " +
"ORDER BY CreatedOn DESC;", partNumbers.ToString());
You might look up the IN clouse for SQL that way you get the answer for the parts that SQL Server can find in the database. Using WHERE x = y for all the items means that if one item can't be found the whole query returns nothing.
I would consider doing this in a stored procedure and passing in your list as an Xml parameter.
See the following article for more info on using Xml parameters in a stored proc:
Passing lists to SQL Server 2005 with XML Parameters - By Jon Galloway
Form there you can easily use your list data inside your stored proc using the Xml syntax and treat it almost as another table of data.
Untested, but you should get the idea:
List<string> ImportedParts = GetImportedPartNumbers();
SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') AND (FilePath NOT LIKE '%js91162%') AND (";
int i = 0;
foreach (string part in ImportedParts) {
cmd.AddParameterWithValue("#param" + i.ToString(), "%" + part + "%");
if (i != 0) cmd.CommandText += " OR"
cmd.CommandText += " PartNumber LIKE #param" + i.ToString();
i++;
}
cmd.CommandText += ") ORDER BY CreatedOn DESC;";
This solution uses a parameterized query instead of just appending strings in the SQL, which is considered a potential security risk.

Categories

Resources