Parametrized query from .net to Oracle - c#

this is my table in oracle:
I'm trying to do this:
selectCmd = "select * from scott.BONUS where ename like '% :f4 %'";
var par = cmd.CreateParameter();
par.DbType = DbType.String;
par.ParameterName = "f4";
par.Value = "fsd";
cmd.Parameters.Add(par);
cmd.CommandText = selectCmd;
con.Open();
my problem is the part after the 'like' .. I've tried many things w/o success.
In some of the tries the reader came back empty while in others an exception has been thrown.

That is looking for something containing the literal sequence of characters space, colon, f, 4. You mean:
like '%' || :f4 || '%'
(edited to reflect correction by Stephen ODonnell, comments)
Or easier; just use
like :f4
And put the % in the value:
par.Value = "%" + "fsd" + "%";
(expanded for convenience, under the assumption that "fsd" needs to be a variable or similar in the real code)

Related

Can you tell whats wrong with the SqlDataReader i returns "System.Data.SqlClient.SqlException: 'Must declare the scalar variable "#idorder"

Hi since I am using the using-statement, my disposable connections should be handled once it leaves the statement but my code is hard coupled in other methods in the program where I poll the db or get information. Therefore I have decided to add conn.Open() and conn.Close() to avoid timeout errors or to leave many Database connections open at the same time. I keep getting an error I am not familiar with and that is:
System.Data.SqlClient.SqlException: 'Must declare the scalar variable "#idorder"
Is it relevant to my paramenter?
What am I doing wrong?
Hope this helps other devs out there starting out with ADO.NET
public List<LogModel> GetLatestLogsOnEachSystemId(
{
List<string> _systemIds = new List<string>();
_systemIds.Add("MA");
_systemIds.Add("MB");
_systemIds.Add("DY");
_systemIds.Add("FA");
using (SqlConnection conn = new SqlConnection(connString))
{
for (int i = 0; i < _systemIds.Count; i++)
{
string systemId = _systemIds[i];
var querystring = "select top 1 * " +
"from dbo.RadarMF30_log " +
"where SYSTEM_ID = #id" +
"order by Log_writing_time desc";
SqlCommand cmd = new SqlCommand(querystring, conn);
conn.Open();
cmd.Parameters.AddWithValue("#id", systemId);
SqlDataReader reader = cmd.ExecuteReader();
conn.Close();
var model = new LogModel
{
errorCode = reader.GetString(0),
errorMsg = reader.GetString(1),
"select top 1 * " +
"from dbo.RadarMF30_log " +
"where SYSTEM_ID = #id" +
"order by Log_writing_time desc";
There is no space between #id and order.
That's why it thinks there is a variable called #idorder
JamesS and Yaman have already covered the fundamental problem, but: as a general tip, if you're going to have SQL in C#, verbatim string literals (#"...") avoid almost all white-space problems:
const string query = #"
select top 1 *
from dbo.RadarMF30_log
where SYSTEM_ID = #id
order by Log_writing_time desc";
(note: it doesn't have to be a const - just... there's also no need for it to be a variable here)
As a side note: this is the kind of scenario that also works very well with tools like "Dapper" to avoid messing with ADO.NET at all:
var model = conn.QuerySingle<LogModel>(#"
select top 1 *
from dbo.RadarMF30_log
where SYSTEM_ID = #id
order by Log_writing_time desc", new { id = systemId });
No more messing with the command and parameter nuances, or worrying about whether you've closed the connection too early (look closely: you've closed the connection too early).
As a side note: you might also want to avoid select * - it can cause two different kinds of problems:
bringing back lots of large columns (CLOB/BLOB etc) that you don't need, impacting performance
sometimes, just sometimes, the columns aren't in the order you expect; if you bind by ordinal (GetString(0) etc in your code), this can have huge impact; note that "Dapper" binds by name, so this isn't as much of a problem here (assuming the names match well enough for the library to figure out what you meant)
because there is no space between #id and order, it thinks the parameter name is #idorder, which is not provided
var querystring = "select top 1 * " +
"from dbo.RadarMF30_log " +
"where SYSTEM_ID = #id " +
"order by Log_writing_time desc";
or
var querystring = "select top 1 * " +
"from dbo.RadarMF30_log " +
"where SYSTEM_ID = #id" +
" order by Log_writing_time desc";

c# parameterized query returns no data/ null values

Using mysql, I am trying to get/set data using parameterized queries, but some of them are returning null, though they working without using parameterized queries. Here are the two I have I had issues with:
This one returns nothing frm the database:
// csvFolder looks ridiculous but this is actually way it needs to look like to work
string csvFolder = "C:\\\\\\\\Users\\\\\\\\fakename\\\\\\\\Desktop\\\\\\\\csvScanner\\\\\\\\testeappfolder"
MySqlCommand deleteCheck = new MySqlCommand("SELECT * FROM email_list WHERE filepath LIKE '%#csvfolder%' AND expired IS NULL", conn);
deleteCheck.Parameters.AddWithValue("#csvfolder", csvFolder);
MySqlDataReader deleteRdr = deleteCheck.ExecuteReader();
But, concatenating the value in will work:
MySqlCommand deleteCheck = new MySqlCommand("SELECT * FROM email_list WHERE filepath LIKE '%" + csvFolder + "%' AND expired IS NULL", conn);
MySqlDataReader deleteRdr = deleteCheck.ExecuteReader();
This one returns null from the ExecuteScalar.
MySqlCommand getId = new MySqlCommand("SELECT * FROM email_list WHERE filepath = '#filepath' ORDER BY expired DESC LIMIT 1", conn);
getId.Parameters.AddWithValue("#filepath", deletedPath.Replace(#"\", "\\\\"));
int id = int.Parse(getId.ExecuteScalar().ToString());
But also works fine when concatenating.
I believe it has to be something with what I am passing (paths with \'s that cause various weirdness), but I cannot see exactly what it is. I have many other parameterized queries for paths that work correctly, but these two do not work. Anyone see something like this before
Because your parameter was within a quoted part of your query, it doesn't get treated like a parameter, It is treated as a literal string that you are searching for. You need to concatenate it like this...
MySqlCommand deleteCheck = new MySqlCommand(
"SELECT * FROM email_list WHERE filepath LIKE '%'+#csvfolder+'%' AND expired IS NULL", conn);
Similar in the ExecuteScalar example:
MySqlCommand getId = new MySqlCommand(
"SELECT * FROM email_list WHERE filepath = #filepath ORDER BY expired DESC LIMIT 1", conn);
Other tips:
MySqlCommand and MySqlDataReader are both IDisposable so each should be in a using block.
You can use literal string to make the string a little easier to follow: string csvFolder = #"C:\\\\Users\\\\fakename\\\\Desktop\\\\csvScanner\\\\testeappfolder" (this still doesn't look right, but it's equivalent to the value you've given).
You may want to read can we stop using AddWithValue.
SELECT * with ExecuteScalar (which only used the first value from the first row) is at risk of breaking in future: safer to select the particular column you are intending to work with.
You're using LIKE to look for a value containing your parameter when the value would appear to be a rooted path. If the value will start with that value, drop the initial wildcard.

SQLParameter incorrect syntax

I have 2 spots where I need to use SQLParameter to parse SQL. One works and one does not and I cannot figure out why the second one doesn't work.
The first one that works is the following:
SqlCommand getShopDbNameCommand = new SqlCommand("SELECT TOP 1 [mappeddbName] FROM [ECM].[dbo].[EcmShop]" +
"WHERE [LicencePassCode] = #licCode AND [iPadLocation] = #shopId", this.mainConnection);
getShopDbNameCommand.Parameters.Add(new SqlParameter("licCode", currUser.LicCode));
getShopDbNameCommand.Parameters.Add(new SqlParameter("shopId", currUser.ShopID));
That works. On top of that, the majority of the tutorials I've read all say that I do not have to have a # in front of the parameter name inside of the new SqlParameter, only inside of the command text itself do I need a # in front of the parameter name.
The second command I am trying to run is the following:
string getAuthCommandText = "SELECT * FROM [" + shopDbName + "].[dbo].[MessageLink]" +
"WHERE [objectname] LIKE %" + "#compareStringA"+ "% OR [objectname] LIKE %" + "#compareStringB" +"%";
SqlCommand getAuthCommand = new SqlCommand(getAuthCommandText, this.mainConnection);
getAuthCommand.Parameters.Add(new SqlParameter("compareStringA", "ABRAUTH"));
getAuthCommand.Parameters.Add(new SqlParameter("compareStringB", "ABRSAUTH"));
This does not work and throws an invalid syntax error. Using breakpoints it still looks like the command is trying to pass the literal #compareString string to SQL and thats whats causing the issue. Ive seen other posts on SOF that say to use the literal parameter name when defining new SqlParameter objects (meaning include the #) but everywhere outside of SoF say otherwise.
Any reason why the second command would throw invalid syntax errors?
your LIKE statements must be inside single quotes
SELECT * FROM Customers WHERE City LIKE '%s%';
the majority of the tutorials I've read all say that I do not have to have a # in front of the parameter name inside of the new SqlParameter,
The C# code for SqlParameter does not care if you put a # in the front or not when adding it to the Parameters collection, it will put a # behind the scenes for you.
For your query that is not working the correct way to do it is you will actually have 3 strings you add together in sql, the two '%' and your parameter. I am also changing the way you add parameters to explicitly set the data type, it is better to do that with strings.
string getAuthCommandText = "SELECT * FROM [" + shopDbName + "].[dbo].[MessageLink]" +
"WHERE [objectname] LIKE ('%' + #compareStringA + '%') OR [objectname] LIKE ('%' + #compareStringB +'%')";
SqlCommand getAuthCommand = new SqlCommand(getAuthCommandText, this.mainConnection);
getAuthCommand.Parameters.Add("#compareStringA", SqlDbType.VarChar, 20).Value = "ABRAUTH"; //I had to guess on your datatype, I just did varchar(20), change as appropriate.
getAuthCommand.Parameters.Add("#compareStringB", SqlDbType.VarChar, 20).Value = "ABRSAUTH";
Try this:
string getAuthCommandText = "SELECT * FROM [" + shopDbName + "].[dbo].[MessageLink] " +
"WHERE [objectname] LIKE " + "#compareStringA"+ " OR [objectname] LIKE " + "#compareStringB" +"";
SqlCommand getAuthCommand = new SqlCommand(getAuthCommandText, this.mainConnection);
getAuthCommand.Parameters.Add(new SqlParameter("compareStringA", "%ABRAUTH%"));
getAuthCommand.Parameters.Add(new SqlParameter("compareStringB", "%ABRSAUTH%"));

Basic SQL - SELECT

So I've got this code:
query2 = "SELECT * from Clicking WHERE ID = '" + ID + "'";
And it seems to make problems with the script, probably I'm mistaken with something here.
For instance, when I write this:
query2 = "SELECT * from Clicking WHERE ID = 3";
..this works just fine, and the script continue with no problems. But with my original code it shows me this error:
OleDbException was unhandled by user code
An exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll but was not handled in user code
Any suggestions how to make this work?
When you use single quotes the 3 is treated as string, and probably your ID column is an int, that's why you are getting the exception .
Also do not use string concatenation, use parameterized queries to prevent SQL injection attacks
query2 = "SELECT * from Clicking WHERE ID = #id";
using(var cmd = new SqlCommand(query2, connection))
{
cmd.Parameters.AddWithValue("#id", ID);
...
}
The way you have the query written it will be like this:
SELECT * from Clicking WHERE ID = '3'
The '' around a number means it will look for an ID as a string that is equal to 3. So you want to remove the single quotes around the number, so it will search for a number that is equal to 3, or whatever number you use. This is what you want:
query2 = "SELECT * from Clicking WHERE ID = " + ID;

How to return the value of query from function?

I have crated one function to return the result of executed SQL query as follows:
EDITED :
public int GetChips(int points, string username)
{
int chip = 0;
string getChips = "SELECT Chips from tbl_UserInfo where UserName =' " + username + " '";
con = new MySqlConnection(conString);
con.Open();
MySqlCommand cmd = new MySqlCommand(getChips, con);
MySqlDataReader chips = cmd.ExecuteReader();
while (chips.Read())
{
chip = chips.GetInt32(0);
if (chip > points)
{
if (points == 5000)
{
chip = chip - 5000;
}
else if (points == 10000)
{
chip = chip - 10000;
}
}
}
con.Close();
return chip;
}
It returns chip's value as 0. This code does not go in 'while' condition.
What can be the problem ?
How can I solve this ?
Well yes... temp is a MySqlDataReader, not an int. You can't assign a MySqlDataReader to a variable of type int.
I suspect you want:
chip = temp.GetInt32(0);
Note that you should use using statements to release all your resources, rather than just closing the connection explicitly. You should also consider what you want to happen if there's more than one result (or no results).
Additionally, your code will fail at execution time at the moment unless the user puts their username in quotes. Don't fix this by adding quotes to the SQL - use parameterized queries instead. Otherwise you're vulnerable to SQL injection attacks. Basically, you should pretty much never build SQL dynamically using values like this - always parameterize them instead.
An answer to your edited question:
Are you sure the select statement is returning any values at all? You have a space inside your ' " and " '" so it will look for ' Rohan ' in stead of 'Rohan'. Try
UserName ='" + username + "'"
Or better yet, like Jon suggested, use parameterized queries!
temp is a MySqlDataReader whereas chip is an int. Of course your can't assign one to the other.
Because your query just returns a value, so you can use this:
chip = (int)(command.ExecuteScalar() ?? 0);
Have a look at following link for more detail:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx

Categories