I'm making a login in asp.net. The query to fetch a user from the database always returns an empty set even when there should be a row back.
I'm using Connector/NET with c#
I have the query to get the user by email declared like this:
select * from users where email = '#email';
In the database I have two rows: test1#example.com and test2#example.com
My code looks like this:
UserByEmail is a string with the query as seen above.
MySqlCommand query = new MySqlCommand(UserByEmail, db);
db.Open();
query.Parameters.AddWithValue("#email", email);
MySqlDataReader reader = query.ExecuteReader();
if(reader.Read()){
/* Do stuff */
}
db.Close();
When I run it like this with any of the test cases, the property reader.HasRows always returns false. I've changed the query directly to:
- select * from users;
- select * from users where email = 'test1#example.com';
And for both of them, there are rows back. So the problem is when I use the parameter #email and the query.Parameters.AddWithValue("#email", email);.
Any idea what's happening here? I've looked for this problem and have find nothing. The code is almost the same as in the doc's example ( Connector/NET Tutorials: Parameters )
Remove ' from sides of '#email' as addwith value adds it where necessary:
string query = "select * from users where email = #email"
By the way, its better to use Parameters.Add(), instead of Parameters.AddWithValue():
command.Parameters.Add("#email", SqlDbType.VarChar).Value = email;
Related
In SQL Server
update incident_info
set description = N'ဆေးလိပ်'
where incidentid = 5
This query is correct in SQL Server and shows myanmar font correctly in the database.
I want to write correct query as above in below insert query.
sqlUtil.SqlDataUpdate(false, ("INSERT INTO Incident_Info (incidentid, incidentdate, incidenttime, description, Salesmen_id, name, phone, email, address, cost, currency, solution, status)" +
"VALUES (#incidentid, #incidentdate, #incidenttime, N'+#description+', #salesmenid, N'+#name+', #phone, #email, N'+#address+', #cost, #currency, N'+#solution+', #status)"), SysController.dicParams);
You do NOT need to prefix your SQL parameter names with a N prefix - that's useless, and probably results in an error. The N prefix is only needed when specifying a Unicode string literal in a raw SQL code snippet.
In your case, what you need to ensure is that the code that does the actual insert into SQL Server properly defines your parameters as SqlDbType.NVarChar. So in your sqlUtil class, somewhere, you have a method SqlDataUpdate that parses and executes that SQL statement you send in.
Inside there, you must ensure that code something like this is used:
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand insertCmd = new SqlCommand(sqlQuery, conn))
{
// here, you need to ensure you define your string parameters correctly
insertCmd.Parameters.Add("#description", SqlDbType.NVarChar, 100);
.....
// and then you need to set the values - since .NET strings are inherently Unicode, no special treatment is needed
insertCmd.Parameters["#description"].Value = SysController.dicParams.......
.....
// open, execute, close
conn.Open();
int rowsInserted = insertCmd.ExecuteNonQuery();
conn.Close();
}
This must be done inside your sqlUtil class - you cannot influence this from the "outside" by simply adding a N prefix to your parameter names...
I'm currently trying to make a book manager in C#. I'm using a .ACCDB Database to store data about the books.
First I retrieve the bookIDs that belong to a specific series with:
sql.CommandText = "select * from BookTable where SeriesID = " +
DataClass.SeriesTableIndex;
It retrieves the BookIDs 20 and 23. These are the correct BookIDs corresponding to the SeriesID in the DB.
After this my code builds the next sql command.
I left out the functional building of the command.
It builds the following code:
string sqlcommand = "select * from BookTable where BookID = 23 or 20"
I use this command to get the book names:
sql.CommandText = sqlcommand;
It should only return bookWithID23 and bookWithID20 but it also returns bookWithID21. There are only 3 books in my testing DB but it somehow returns all 3 instead of the 2 in the series.
I don't really know anything about SQL so it's probably a simple syntax error.
The correct syntax of or is (https://www.w3schools.com/sql/sql_and_or.asp):
"BookID = 23 or BookID = 20"
Also you should always use parameterized queries to avoid SQL Injection, something like this:
sql.CommandText = "select * from BookTable where SeriesID = #SeriesID";
sql.Parameters.AddWithValue("#SeriesID", DataClass.SeriesTableIndex);
Although specify the type directly and use the Value property is more better than AddWithValue:
sql.Parameters.Add("#SeriesID", SqlDbType.Int).Value = DataClass.SeriesTableIndex;
Can we stop using AddWithValue() already?
I'm having trouble with a simple SELECT query, I cannot see why it isn't working.
Here is the code:
conn.Open();
string GetPayrollQuery = "SELECT PayrollNo FROM [Employee] WHERE (FirstName + ' ' + LastName) = #Name";
OleDbCommand GetPayroll = new OleDbCommand(GetPayrollQuery, conn);
GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text;
var GotPayroll = GetPayroll.ExecuteNonQuery();
MessageBox.Show(GotPayroll.ToString());
return Convert.ToInt32(GotPayroll);
The code runs fine however it isn't extracting the data. Can anyone see why this would be?
I bet #name is coming as "MikeSmith" instead of "Mike Smith".
3 things:
try to open SQL profiler and check what you are executing on database
check database collation, is it case sensitive?
remove executenonquery (it's must used with update, delete, not select) and try executescalar (if one result for one row is exptected, otherwise try to fill a datatable or use datareader)
Make sure the same query runs in SQL using those parameter values.
Change GetPayroll.ExecuteNonQuery() to GetPayroll.ExecuteScalar() so to return a single result.
Change GetPayroll.Parameters.AddWithValue("#Name", OleDbType.VarChar).Value = cbbEmployees.Text; to GetPayroll.Parameters.AddWithValue("#Name", cbbEmployees.Text);
Use cbbEmployees.SelectedText. Fixes the problem.
How do I make it so that my query only update the data I want?
Here's the current code
string query = string.Format("update Customer set title='{0}',[Name]='{1}'",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox+"");
Apparently the last part of the query isn't working. Why it is that?
Because you didn't use any index argument as {2} for your third argument which is WHERE part.
That's why your query will be contain only update Customer set title='{0}',[Name]='{1}' part this will be update for your all rows since it doesn't have any filter.
Fun fact, you could see this as query if you would debug your code.
But more important
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Let's assume you use ADO.NET;
using(var con = new SqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"update Customer set title = #title, [Name] = #name
where ID = #id";
cmd.Paramter.Add("#title", SqlDbType.NVarChar).Value = titleComboBox2.Text;
cmd.Paramter.Add("#name", SqlDbType.NVarChar).Value = nameTextBox2.Text;
cmd.Paramter.Add("#id", SqlDbType.Int).Value = int.Parse(idTextBox.Text);
// I assumed your column types.
con.Open();
cmd.ExecuteNonQuery();
}
Currently your query does not use WHERE clause, because it is ignored by string.Format. You have 3 placeholder parameters, and you are using only {0} and {1}, so WHERE part is never added to the SQL query. Change your query to include WHERE clause, e.g. like this:
string query = string.Format("update Customer set title='{0}',[Name]='{1}' {2}",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox.Text+"");
However, there is one very serious flaw in your code - it is vulnerable to SQL injection attack. There are hundreds of articles about it online, make sure to read about what that is and how to update your code accordingly (hint - parametrize queries)
I've got a function that stores temporary information generated for every user authenticated in the system. This 'session ID' is a string stored in a Sessions table, along the original ID of the user which authenticated and was given said session identifier.
The function to remove/deauthenticate/invalidate an existing session first checks if the user exists through another method implemented as follows:
int userId = 0;
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#User", userName);
cmd.Connection = this.conn;
cmd.CommandText = "SELECT Id FROM Users WHERE (Username = #User)";
userId = (int) cmd.ExecuteScalar()
cmd.Dispose();
Afterwards it tries to find an existing session for that user, which is to be removed (via a different method again):
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#SID", mysession);
sqlParams.AddWithValue("#UID", myuserid);
cmd.Connection = this.Connection;
cmd.CommandText = "SELECT Id FROM UserSessions WHERE (SessionID = #SID) AND (User_Id = #UID)";
int foo = cmd.ExecuteNonQuery();
...which fails. No exception is raised unfortunately. So I added an insecure equivalent using a non parametrized query string:
cmd.CommandText = String.Format("SELECT Id FROM UserSessions WHERE (SessionID = '{0}') AND (User_Id = {1})", mysession, myuserid);
cmd.Prepare();
int bar = cmd.ExecuteNonQuery();
Added a breakpoint, paused, copy pasted the query into the Visual Studio Query tool and voila, it indeed worked. But after continuing, that query in the code failed as well. I'm unable to find the culprit of this annoying issue since no exception is raised and everything seems correct. The data exists, the parameters are provided in proper types (string and int) and I'm out of things to check. The connection is open and so forth.
Any clues from anyone around? Thanks!
Update: Mea culpa, missed the fact that the function used ExecuteScalar until I modified it for testing. It does use ExecuteScalar and returns null, just in case.
You're using ExecuteNonQuery:
int foo = cmd.ExecuteNonQuery();
... but you're clearly trying to execute a query (a SELECT)! Use ExecuteScalar again, as you did in the first code, or ExecuteReader and look through the results appropriately. If you stick with ExecuteScalar, you should first check whether the result is null to indicate no results.
ExecuteNonQuery returns the number of rows affected by an UPDATE/INSERT/DELETE command - which is what it's intended for. I suspect it's returning -1 for you, as documented:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
(Emphasis mine.)
Use set [] to avoid ambiguity with database keyword.
cmd.CommandText = "SELECT [Id] FROM [Users] WHERE ([Username] = #User)";
and use ExecuteScalar() or ExecureReader() method when working with SELECT statements.