The following query in C# doesn't work, but I can't see the problem:
string Getquery = "select * from user_tbl where emp_id=#emp_id and birthdate=#birthdate";
cmdR.Parameters.AddWithValue("#emp_id", userValidate.emp_id);
cmdR.Parameters.AddWithValue("#birthdate", userValidate.birthdate);
OdbcCommand cmdR = new OdbcCommand(Getquery, conn);
OdbcDataReader Reader = cmdR.ExecuteReader();
Reader.HasRows returns no result but when I query it to my database I got data.
I'll assume your code is actually not quite as presented, given that it wouldn't currently compile - you're using cmdR before you declare it.
First, you're trying to use named parameters, and according to the documentation of OdbcCommand.Parameters, that isn't supported:
When CommandType is set to Text, the .NET Framework Data Provider for ODBC does not support passing named parameters to an SQL statement or to a stored procedure called by an OdbcCommand. In either of these cases, use the question mark (?) placeholder.
Additionally, I would personally avoid using AddWithValue anyway - I would use something like:
string sql = "select * from user_tbl where emp_id = ? and birthdate = ?";
using (var connection = new OdbcConnection(...))
{
connection.Open();
using (var command = new OdbcCommand(sql, connection))
{
command.Parameters.Add("#emp_id", OdbcType.Int).Value = userValidate.EmployeeId;
command.Parameters.Add("#birthdate", OdbcType.Date).Value = userValidate.BirthDate;
using (var reader = command.ExecuteReader())
{
// Use the reader here
}
}
}
This example uses names following .NET naming conventions, and demonstrates properly disposing of resources... as well as fixing the parameter issue.
I do think it's slightly unfortunate that you have to provide a name for the parameter when adding it to the command even though you can't use it in the query, but such is life.
Use like this:
string Getquery = "select * from user_tbl where emp_id=? and birthdate=?";
cmdR.Parameters.AddWithValue("#emp_id", userValidate.emp_id);
cmdR.Parameters.AddWithValue("#birthdate", userValidate.birthdate);
OdbcCommand cmdR = new OdbcCommand(Getquery, conn);
OdbcDataReader Reader = cmdR.ExecuteReader();
while(Reader.Read())
{
//Do something;
}
I know this thread is old, but I wanted to share my solution for anyone else coming up on this.
I was having issues with the typical method that Jon posted. I have used it before, but for some reason with this new string I had it was not wanting to actually place the parameter correctly and was causing the reader to not work.
I ended up doing something like this instead, since in the end we are just replacing parts of a string.
string sql = "select * from user_tbl where emp_id = "+ var1 +" and birthdate = "+
var2""
OdbcCommand command = new OdbcCommand(sql);
This was easier for me to get to work. Be warned though, I am not sure if it has any specific drawbacks when compare to using the command parameter method.
Related
I have a SQL command I am running that works great however for one of the AddWithValue parameters I want to use another SQL command to get that value... this is what I have but the cmd2 I want to use isn't working. Is it even possible to get data that way in theory it makes sense but it doesn't seem to work..
cmd2 = new SqlCommand("SELECT acctNum FROM custInfo WHERE customerName = #customerName", cn);
cmd2.Parameters.AddWithValue("#customerName", customerDropDown.Text);
cmd = new SqlCommand("UPDATE custInfo SET ctGal = (ctGal - (#contractGallons)) WHERE acctNum = #acctNum", cn);
cmd.Parameters.AddWithValue("#contractGallons", gallonsTextBox.Text)
cmd.Parameters.AddWithValue("#acctNum", cmd2);
I suggested combining both queries into one:
//DONE: let keep query readable
string sql =
#"UPDATE custInfo
SET ctGal = (ctGal - (#contractGallons))
WHERE acctNum IN (SELECT c.acctNum
FROM custInfo c
WHERE c.customerName = #customerName)";
//DONE: wrap IDisposable into using
using (var cmd = new SqlCommand(sql, cn)) {
//TODO: get rid of AddWithValue, but specify the actual fields' types
cmd.Parameters.AddWithValue("#contractGallons", gallonsTextBox.Text);
cmd.Parameters.AddWithValue("#customerName", customerDropDown.Text);
cmd.ExecuteNonQuery();
}
You have two choices if you want to go this route:
Combine the two queries when you instantiate the second SqlCommand. This will require adding a second parameter to the second command.
Or run the first command. Fetch the resulting acctNum and add it as a value for the second command.
Probably better would be to rewrite the two queries into a single joined query.
You must use cmd2.ExecuteReader() to get the acctNum for example
You can try following code
using (SqlDataReader reader = cmd2.ExecuteReader())
{
if (reader.Read())
{
cmd = new SqlCommand(#"UPDATE custInfo SET ctGal = (ctGal -
(#contractGallons)) WHERE acctNum = #acctNum", cn);
cmd.Parameters.AddWithValue("#contractGallons", gallonsTextBox.Text)
cmd.Parameters.AddWithValue("#acctNum", reader["acctNum"]);
}
}
Hope this will help..
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
}
I have an insert query to execute from within a C# against a SQL Server database.
The column I am inserting to is of type nvarchar.
the data I am inserting to that column is non-english.
Is it sufficient for me to use AddWithValue in order to pass the non-english data to the server? like this example:
string dogName = "עברית";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO Dogs1(Name) VALUES #Name", connection))
{
command.Parameters.AddWithValue("Name", dogName);
command.ExecuteNonQuery();
}
}
Or must I use the N prefix to declare it unicode? like it says so here.
If I am understanding the question correctly, you can explicitly set the SqlCommand parameter to be a specific data type. You will be able to set it to be nvarchar as shown by the following link: http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx
This below code snippet is taken directly from MSDN:
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#CategoryName";
parameter.SqlDbType = SqlDbType.NVarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = categoryName;
This uses an explicitly created SqlParameter instance, but it is the same idea by indexing the SqlParameterCollection of the SqlCommand instance.
I believe the link at the bottom is only really talking about values within SQL itself.
As far as I'm aware, the code you've got should be absolutely fine - otherwise there'd be no way of specifying Unicode text.
Of course, it's probably worth validating this - but I'd be very surprised if it didn't work.
I have some queries (to an acccess database) like this :
string comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL='" + user + "' AND PASSWORD_AZIENDA='" + password + "'";
and I'd like to "escape" user and password, preventing an injection.
How can I do it with C# and .NET 3.5? I'm searching somethings like mysql_escape_string on PHP...
You need to use parameters. Well dont have to but would be preferable.
SqlParameter[] myparm = new SqlParameter[2];
myparm[0] = new SqlParameter("#User",user);
myparm[1] = new SqlParameter("#Pass",password);
string comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL=#User AND PASSWORD_AZIENDA=#Pass";
Don't escape the strings to start with - use a parameterized query. Benefits of this over escaping:
The code is easier to read
You don't have to rely on getting the escaping correct
It's possible that there are performance improvements (DB-specific etc)
It separates "code" (the SQL) from the data, which is just good sense logically
It means you don't need to worry about data formats for things like numbers and dates/times.
The docs for SqlCommand.Parameters give a good, complete example.
You should use the SQL paramters to prevent SQL Injection
look at the code
//
// The name we are trying to match.
//
string dogName = "Fido";
//
// Use preset string for connection and open it.
//
string connectionString = ConsoleApplication716.Properties.Settings.Default.ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
//
// Description of SQL command:
// 1. It selects all cells from rows matching the name.
// 2. It uses LIKE operator because Name is a Text field.
// 3. #Name must be added as a new SqlParameter.
//
using (SqlCommand command = new SqlCommand("SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int weight = reader.GetInt32(0);
string name = reader.GetString(1);
string breed = reader.GetString(2);
Console.WriteLine("Weight = {0}, Name = {1}, Breed = {2}", weight, name, breed);
}
}
}
Yes, you can avoid injection by using Named Parameters
Use parameters instead of escaping strings:
var comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL=#user AND PASSWORD_AZIENDA=#password";
Then assign values to those parameters before you execute the SqlCommand.
You can check the below link to know how to prevent SQL injection in ASP.Net. I would prefer to use
Using parametrized queries or Stored Procedures.
Validating special characters like '(very dangerous)
http://dotnet.dzone.com/news/aspnet-preventing-sql-injectio
If you can convert these to Named Parameters, I think you would be better served.
#Jethro
You could also write it like this:
SqlParameter[] sqlParams = new SqlParameter[] {
new SqlParameter("#Name", contact.name),
new SqlParameter("#Number", contact.number),
new SqlParameter("#PhotoPath", contact.photoPath),
new SqlParameter("#ID", contact.id)
};
Follow the steps below and resolve the SQL INJECTION problem:
OracleParameter[] tmpParans = new OracleParameter[1];
tmpParans[0] = new Oracle.DataAccess.Client.OracleParameter("#User", txtUser.Text);
string tmpQuery = "SELECT COD_USER, PASS FROM TB_USERS WHERE COD_USER = #User";
OracleCommand tmpComand = new OracleCommand(tmpQuery, yourConnection);
tmpComand.Parameters.AddRange(tmpParans);
OracleDataReader tmpResult = tmpComand.ExecuteReader(CommandBehavior.SingleRow);
I was hoping to find an easy way to get a parameter list of a stored procedures parameters. If the procedure has 3 paramaters, I want a list like this:
param1
param2
param3
It would be best to be able to do this in C# Code, but SQL would suffice as well. Ideas?
select * from information_schema.parameters
where specific_name='your_procedure_name'
Also refer this post to know more methods
https://exploresql.com/2016/10/14/different-methods-to-get-parameter-list-of-a-stored-procedure/
For SQL Server this should work.
private void ListParms()
{
SqlConnection conn = new SqlConnection("my sql connection string");
SqlCommand cmd = new SqlCommand("proc name", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlCommandBuilder.DeriveParameters(cmd);
foreach (SqlParameter p in cmd.Parameters)
{
Console.WriteLine(p.ParameterName);
}
}
You can do this without ever touching SqlConnection, which I find is a bonus.
This uses the SqlServer.Management.Smo namespace, so you need a reference to Microsoft.SqlServer.ConnectionInfo, Microsoft.SqlServer.Management.Sdk, and Microsoft.SqlServer.Smo in your project.
Then use the following code:
Server srv = new Server("serverNameHere");
srv.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
srv.ConnectionContext.LoginSecure = false; //if using username/password
srv.ConnectionContext.Login = "username";
srv.ConnectionContext.Password = "password";
srv.ConnectionContext.Connect();
Database db = srv.Databases["databaseNameHere"];
foreach(StoredProcedure sp in db.StoredProcedures)
{
foreach(var param in sp.Parameters)
{
string paramName = param.Name;
var dataType = param.DataType;
object defaultValue = param.DefaultValue;
}
}
If you're familiar with Enterprise Library, there's a good method which allows to DiscoverParameters(), using the Data Access Application Block.
DbCommand command = new DbCommand();
command.CommandText = #"myStoredProc";
command.CommandType = CommandType.StoredProcedure;
Database database = new SqlDatabase(myConnectionString);
database.DiscoverParameters(command);
// ...
Some links that might help:
DiscoverParameters Method;
Microsoft.Practices.EnterpriseLibrary.Data Namespace.
The above links refers to EntLib 3.1. Depending on the .NET Framework version you're using, you might also consider downloading the correct EntLib version for you following this link.