reading data with OleDbDataReader - c#

I'm trying to get the value of a Field (User Access level it's 1 or 2 in string format) after login
OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=dsms.accdb");
connection.Open();
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("SELECT AL From Users WHERE Username='" + textusername.text + "'", connection);
reader = command.ExecuteReader();
if( reader.HasRows)
{
MessageBox.Show("success","status");
label1.Text = reader.GetString(1);
}
else
MessageBox.Show("failur", "status");
connection.Close();
I did execute the code in Access and it's was totally fine
but in the program, it says "No data exist for the row/column"

The main problem in your code is the fact that you need to call reader.Read() to get anything out from a DataReader. Just calling HasRows doesn't position the reader on the first record of your query.
There are other problems in your code.
Disposable objects like connections, commands and readers should be created in a using statement to ensure proper disposition after use and because you have only one field in your query, you should use the index 0 to retrieve it not 1.
Finally the most important one. You should NEVER concatenate strings to build an sql query. In this way a malicious user could write anything in your textbox, even valid sql commands that could be executed against your database. It is called Sql Injection and if you search for these terms you will find very detailed discussions about it. However, to avoid this problem (and others like parsing input with apostrophes) you use a parameterized query like below.
using(OleDbConnection connection = new OleDbConnection(.....))
using(OleDbCommand command = new OleDbCommand("SELECT AL From Users WHERE Username=#name", connection);
{
connection.Open();
command.Parameters.Add("#name", OleDbType.VarWChar).Value = txtusername.text;
using(OleDbDataReader reader = command.ExecuteReader())
{
if( reader.Read())
{
MessageBox.Show("success","status");
label1.Text = reader.GetString(0);
}
else
MessageBox.Show("failur", "status");
}
}

Related

How do I solve error in ExecuteReader();?

I am facing an issue with ExecuteReader(). When I am writing MySqlDataReader reader = cmd.ExecuteReader();, I have a red line under cmd.ExecuteReader(). I am using Windows Form Application to read database from Microsoft SQL Server and using C# and OOP.
SqlConnection con = new SqlConnection(constring);
con.Open();
if (con.State == System.Data.ConnectionState.Open)
{
string q = "SELECT * from BuildingA30 where CONVERT(VARCHAR, FlatNo) = N'" + a11 + "' ";
Console.WriteLine("Read all");
Console.WriteLine(q);
SqlCommand cmd = new SqlCommand(q, con);
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
textBox1.Text = reader.GetString("tenantname");
textBox2.Text = reader.GetString("FlatNo");
}
textBox1.Text = q.ToString();
MessageBox.Show("Connection success");
}
Problem is that SqlCommand.ExecuteReader returns a SqlDataReader, not a MySqlDataReader.
Here:
SqlCommand cmd = new SqlCommand(q, con);
MySqlDataReader reader = cmd.ExecuteReader();
You're mixing ADO.NET providers. Either use the SQL Server provider classes (if the database is SQL Server), or the MySql ones if it's MySql. Not both.
You install Dapper, then you don't have to waste your life writing boring, menial data reader code..
With Dapper that entire code you've written (yep all of it) would become something like `
using(var con = new MySqlConnection(...)){
var rental = con.Query<RentalInfo>(
"SELECT * FROM BuildingA30 WHERE flatNo = #f",
new { f = all }
};
//use your rental object
This code is massively improved over the one you have there because:
it's simple, quick to write, easy to read and debug
it uses parameters and doesn't suffer from sql injection hacking risks - yours does
it is strongly typed and can be async (note, mysql hasn't implemented async for their db provider, apparently but using async is a good habit to get into) - you just need to create a class called RentalInfo and add the relevant names properties to it;
it doesn't call functions on the left hand side of an operator in the WHERE clause. Always a bad idea; don't call functions on millions of rows, call functions on constants and leave table data alone
http://dapper-tutorial.net
Note: I have no affiliation to Dapper or the guys who maintain that tutorial site

Error says "No value given for one or more required parameters"

Is there anything wrong with my codes? Because, I'm about to create a login form and it doesn't.
OleDbConnection conDataBase = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0; Data Source = C:\Users\tess\Documents\iknow.accdb;" + "Persist Security Info = True");
OleDbCommand cmdDataBase = new OleDbCommand(" select * from iknow where Username = '"+user_NameTextBox.Text+"'");
cmdDataBase.Connection = conDataBase;
OleDbDataReader myReader;
conDataBase.Open();
myReader = cmdDataBase.ExecuteReader();
int count = 0;
while (myReader.Read())
{
count = count + 1;
}
if (count == 1)
{
MessageBox.Show("Login Successful");
}
else
{
MessageBox.Show("Invalid Username");
}
You have a couple issues, as Jon Skeet pointed out you've introduced a SQL injection vulnerability, aren't implementing the using syntax to dispose of resources correctly, and have a parameter but aren't actually implementing (this is hard to identify, without more code or what flagged this error).
var query = "SELECT TOP 1 [Id] FROM User WHERE Username = #Username";
using(var connection = new OleDbConnection(path))
using(var command = new OleDbCommand(query, connection))
{
connection.Open();
command.Parameters("Username", txtUsername.Text());
using(var reader = command.ExecuteReader())
while(reader.Read())
{
// Do something.
}
}
So the above code would address the following:
Injection point
Disposing resources
Correctly associating command to connection
No reason to * for everything, if you only want to see if it exists.
You should really only have a single username, so TOP 1 could refine.
You also could use ExecuteScalar instead of reader, that way you can simply validate the record was returned. This would alleviate the need to iterate through the returned record set. If you TOP 1 and ensure only one username exists, won't matter but it is an option.
As for your parameter, we would need more information. The debugger should tell you which line is throwing the exception. Those details could help resolve the issue.

Inserting data into a MS Access database

try
{
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;");
myConnection.Open();
// Create Oledb command to execute particular query
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = myConnection;
// Query to create table with specified data columne
myCommand.CommandText = "CREATE TABLE UXZona([IDZona] int, [Morada] text)";
//myCommand.ExecuteNonQuery();
MessageBox.Show("Tabela criada");
}
catch
{
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;");
myConnection.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO UXZona (IDZona, Morada) VALUES ('" +
transaction.UnloadPlaceAddress.AddressID + "','" +
transaction.UnloadPlaceAddress.AddressLine2 + "')";
cmd.ExecuteNonQuery();
MessageBox.Show("Dados inseridos");
}
I need to insert data into the database but it isn't working. I launch the program and there are no errors, I do everything but when I check the database the table is empty.
UPDATE
Now when i launch the program I have this error:
"System.InvalidOperationException: 'ExecuteNonQuery: Connection property has not been initialized." on cmd.ExecuteNonQuery();
There are a number of things wrong! I give below corrected code:
try
{
bool success = false;
using (var myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;"))
{
// Create Oledb command to execute particular query
using (var myCommand = new OleDbCommand())
{
myCommand.Connection = myConnection;
// Query to create table with specified data columne
//myCommand.CommandText = "CREATE TABLE UXZona([IDZona] int, [Morada] text)";
//myCommand.ExecuteNonQuery();
//MessageBox.Show("Tabela criada");
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO UXZona (IDZona, Morada) VALUES (#id, #morada)";
var param = cmd.CreateParameter();
param.ParameterName = "#id";
param.OleDbType = OleDbType.Integer;
param.Value = transaction.UnloadPlaceAddress.AddressID;
cmd.Parameters.Add(param);
param = cmd.CreateParameter();
param.ParameterName = "#morada";
param.OleDbType = OleDbType.VarChar;
param.Value = transaction.UnloadPlaceAddress.AddressLine2;
cmd.Parameters.Add(param);
myConnection.Open();
if (cmd.ExecuteNonQuery() == 1)
{
success = true;
}
}
}
if (success)
{
MessageBox.Show("Dados inseridos");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
By way of explanation. I have commented out (but not deleted) all references to creating the table. Table creation and table insertion should be in two different routines. Normally you only create a table once, but insert is probably called many times.
I have placed the OleDbConnection and OleDbCommand within using loops. This is good practice, as they both implement IDisposable. Writing your code like this means that the Garbage Collector (GC) knows immediately that it can safely dispose of the objects after use.
I have changed the insert statement such that it takes parameters. This is highly recommended practice to safeguard against SQL Injection (if you do not know what this is please Google it). In fact Access is relatively immune from the worst forms of SQL Injection, because it rejects any command that contains multiple statements, but please get into good habits. With time you will progress to other databases which do not have this restriction.
I deliberately wait before opening the connection until just before it is needed. Connections consume resources, so it is good practice to use them as sparingly as possible. Also for this reason, I have moved your success message outside of the using loops. This means that the cleanup of resources is not waiting for the user to click OK in the message box.
Finally try catch is all well and good, but normally you want to know why the error occurred. Hence you add (Exception ex) to catch so that you can find the reason.
PS What I forgot to mention. In your original INSERT, you were surrounding both VALUES with single quotes. Only use single quotes for strings/text. Integers and other numbers require no quotes. If you quote them, the database will treat it as a string and you will get a data type error.

MySqlCommand in Asp.net WEB Forms to Display in Label

i have this sql command
string myreg = "select registration_no from truck where truck_id ='" + truckID + "'";
MySqlCommand cmd = new MySqlCommand(myreg, conn);
i want to put the value of myreg to my RegistrationNo.Text label.
i have this RegistrationNo.Text = myreg; and it displays select registration_no from truck where truck_id on my page
You need to read something about the workings of ADO.NET and its providers.
To get the result of that query in your textbox you need
Open a connection to your MySql Server
Prepare a command to send to the Server
Get back the result
Write the result to your textbox
All these passages requires the use of specific classes and some code to glue everything together
// Prepare your command using a parameter placeholder
string myreg = "select registration_no from truck where truck_id =#id";
// Build the connection to the server and build the command to execute
using (MySqlConnection cnn = new MySqlConnection(.... the connection string that identifies your server and db ))
using (MySqlCommand cmd = new MySqlCommand(myreg, cnn))
{
// Open the connection
cnn.Open();
// Add the parameter expected
cmd.Parameters.Add("#id", MySqlDbType.VarChar).Value = truckID;
// Execute the command and get back the return value (if found)
object result = cmd.ExecuteScalar();
// Check if the ExecuteScalar has returned something
if(result != null)
RegistrationNo.Text = result.ToString();
else
... message to your user about the failed search ...
}
PS. I have assumed that your variable truckID is a string because in your original code you have passed it between single quotes, but if it is an integer then you need to modify the parameter type to MySqlDbType.Int32
Also, I have used the ExecuteScalar method instead of ExecuteReader because I think that your query returns just a row with a single column and for this task it is better to use ExecuteScalar
You can use datareader also.See MSDN documentation here.
using (connection)
{
SqlCommand command = new SqlCommand(
"SQL Query",
connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
reader.GetString(1));
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
}

How do I retrieve the result of an ADO.NET SqlCommand?

Ok either I'm really tired or really thick at the moment, but I can't seem to find the answer for this
I'm using ASP.NET and I want to find the amount of rows in my table.
I know this is the SQL code: select count(*) from topics, but how the HECK do I get that to display as a number?
All I want to do is run that code and if it = 0 display one thing but if it's more than 0 display something else. Help please?
This is what I have so far
string selectTopics = "select count(*) from topics";
// Define the ADO.NET Objects
SqlConnection con = new SqlConnection(connectionString);
SqlCommand topiccmd = new SqlCommand(selectTopics, con);
if (topiccmd == 0)
{
noTopics.Visible = true;
topics.Visible = false;
}
but I know I'm missing something seriously wrong. I've been searching for ages but can't find anything.
PHP is so much easier. :)
Note that you must open the connection and execute the command before you can access the result of the SQL query. ExecuteScalar returns a single result value (different methods must be used if your query will return an multiple columns and / or multiple rows).
Notice the use of the using construct, which will safely close and dispose of the connection.
string selectTopics = "select count(*) from topics";
// Define the ADO.NET Objects
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand topiccmd = new SqlCommand(selectTopics, con);
con.Open();
int numrows = (int)topiccmd.ExecuteScalar();
if (numrows == 0)
{
noTopics.Visible = true;
topics.Visible = false;
}
}
ExecuteScalar is what you're looking for. (method of SqlCommand)
Btw, stick with C#, there's no way PHP is easier. It's just familiar.
You need to open the connection
This might work :
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "select count(*) from topics";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
sqlConnection1.Close();
Similar Question: C# 'select count' sql command incorrectly returns zero rows from sql server

Categories

Resources