Hey guys I am using C# and I've successfully accessed my database and assigned variables etc but I want to access it a second time and for some reason it's failing at this point:
OleDbDataReader reader = command.ExecuteReader();
Here is the code snippets that might help you guys understand better. If anyone can point out what I might be doing wrong I'd be deeply grateful.
//#########################
// DATABASE OPERATIONS
//#########################
// Create the database connections
string usersConnString = (#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\kronix\Documents\theitguy.accdb");
OleDbConnection theitguyDBConn = new OleDbConnection(usersConnString);
//==============================
// Populate Customers Table
//==============================
try
{
// Open theitguy database connection
theitguyDBConn.Open();
// Select the fields you want to retrieve from in the database
string selectString = "SELECT ID, Name, Surname, Address, Town, County, Postcode, HomeNumber, MobileNumber, Email FROM Customers";
OleDbCommand command = new OleDbCommand(selectString, theitguyDBConn);
//Send the CommandText to the connection, and then build an OleDbDataReader.
//Note: The OleDbDataReader is forward-only.
OleDbDataReader reader = command.ExecuteReader();
// PROCESS THE DATABASE AND ADD THEM TO THE LISTS FOR USE LATER IN THE PROGRAM
while (reader.Read())
{
custID.Add(reader["ID"].ToString());
custName.Add(reader["Name"].ToString());
custSurname.Add(reader["Surname"].ToString());
custAddress.Add(reader["Address"].ToString());
custTown.Add(reader["Town"].ToString());
custCounty.Add(reader["County"].ToString());
custPostcode.Add(reader["Postcode"].ToString());
custHomeNumber.Add(reader["HomeNumber"].ToString());
custMobileNumber.Add(reader["MobileNumber"].ToString());
custEmail.Add(reader["Email"].ToString());
}
// Dispose of the data once used
reader.Dispose();
reader.Close();
// Close the database connection
theitguyDBConn.Close();
}
catch (Exception ex)
{
Console.Write("ERROR 201 (Form2): Error reading Customers table in theitguy Database\n");
}
//==============================
// Populate Repairs Table
//==============================
try
{
// Open theitguy database connection
theitguyDBConn.Open();
// Select the fields you want to retrieve from in the database
string selectString = "SELECT ID, CustID, Name, Surname, DateIn, Device, Colour, ContactNumber1, ContactNumber2, EstimatedCost, ReportedProblem, Diagnostics, EngineerRemarks, WorkCompleted, PartsUsed, PartsCost, PartsID, Engineer, TotalCost, DateCompleted FROM Repairs";
OleDbCommand command = new OleDbCommand(selectString, theitguyDBConn);
//Send the CommandText to the connection, and then build an OleDbDataReader.
//Note: The OleDbDataReader is forward-only.
OleDbDataReader reader = command.ExecuteReader(); //###IT'S FAILING HERE!!!###
// PROCESS THE DATABASE AND ADD THEM TO THE LISTS FOR USE LATER IN THE PROGRAM
while (reader.Read())
{
repID.Add(reader["ID"].ToString());
repCustID.Add(reader["ID"].ToString());
repName.Add(reader["ID"].ToString());
repSurname.Add(reader["ID"].ToString());
repDateIn.Add(reader["ID"].ToString());
repDevice.Add(reader["ID"].ToString());
repColour.Add(reader["ID"].ToString());
repContactNumber1.Add(reader["ID"].ToString());
repContactNumber2.Add(reader["ID"].ToString());
repEstimatedCost.Add(reader["ID"].ToString());
repReportedProblem.Add(reader["ID"].ToString());
repDiagnostics.Add(reader["ID"].ToString());
repEngineerRemarks.Add(reader["ID"].ToString());
repWorkCompleted.Add(reader["ID"].ToString());
repPartsUsed.Add(reader["ID"].ToString());
repPartsCost.Add(reader["ID"].ToString());
repPartsID.Add(reader["ID"].ToString());
repEngineer.Add(reader["ID"].ToString());
repTotalCost.Add(reader["ID"].ToString());
repDateCompleted.Add(reader["ID"].ToString());
}
// Dispose of the data once used
reader.Dispose();
reader.Close();
// Close the database connection
theitguyDBConn.Close();
}
catch (Exception ex)
{
Console.Write("ERROR 202 (Form2): Error reading Repairs table in theitguy Database\n");
}
Whoopsie, I made a boo boo .... I found out my problem.
I forgot to name the following properly:
repCustID.Add(reader["ID"].ToString());
repName.Add(reader["ID"].ToString());
repSurname.Add(reader["ID"].ToString());
Should be
repCustID.Add(reader["CustID"].ToString());
repName.Add(reader["Name"].ToString());
repSurname.Add(reader["Surname"].ToString());
Silly me.
Actually that wasn't the only fault...... the REAL PROBLEM was that I was trying to convert currency type in access into a string.
Related
I am developing a login system using ASP.NET 7.0. I have created the login and signup system, by connecting to an SQL database and inserting or querying it for information. Currently, the backend code is able to create accounts, and check to make sure that while making an account, that their is no user with matching email or username. I would like to be able to display some sort of message saying "An account with those details has already been created, Login?". How would I go about this?
Here is my current code:
public void OnPostSignup()
{
System.Diagnostics.Debug.WriteLine("Post Request Received");
// Creating Credentials //
string InputUser = Request.Form["signup-user"];
string InputPassword = Request.Form["signup-pwd"];
string InputEmail = Request.Form["signup-email"];
// Creates a new SQL Connection using the connection string provided - Then runs an SQL Command: NOTHING HAS BEEN RUN YET, ONLY INSTANCIATED //
using (SqlConnection conn = new SqlConnection("Valid Server String Here"))
using (SqlCommand cmd = new SqlCommand("INSERT INTO AccountData ([User], [Password], [Email]) VALUES (#1, #2, #3);", conn))
{
// The Placeholder Values are replaced with the string variables created above containing our account registration data //
cmd.Parameters.AddWithValue("#1", InputUser);
cmd.Parameters.AddWithValue("#2", InputPassword);
cmd.Parameters.AddWithValue("#3", InputEmail);
// Instanciates a new SQL Command that will cehck the database to ensure an account with that infomation hasnt been created already //
using (SqlCommand UserCheck = new SqlCommand("SELECT * FROM AccountData WHERE [User] = #1 AND [Email] = #2", conn))
{
// Adds the inputted data into the UserCheck SQL Command //
UserCheck.Parameters.AddWithValue("#1", InputUser);
UserCheck.Parameters.AddWithValue("#2", InputEmail);
// A connection to our SQL Databasse is opened //
conn.Open();
// Executes a data reader on our SQL Server
SqlDataReader reader= UserCheck.ExecuteReader();
// This logic gate checks if the reader returns any rows with the given infomation - if yes, no account is created, and the connection is closed - if no, the account creation is started //
if(reader.HasRows)
{
// We already have an account with the same email or username //
reader.Close();
conn.Close();
// Display some sort of message to the user saying that their email or username is already in use. //
}
else
{
// We do not have an account with that information - An account can now be created //
// Closes the reader, because we cannot query our SQL databse twice at the same time //
reader.Close();
// Executes the 'cmd' SQL command against our SQL Databse //
cmd.ExecuteNonQuery();
// Closes the connection to our SQL Databse for security - and cost //
conn.Close();
}
}
}
}
// This will run when the user clicks the "Login button, after filling out all the required fourm felids //
public void OnPostLogin()
{
// Takes the data inputted by the user, and stores them as variables to be ran against the SQL Database //
string LoginUser = Request.Form["login-user"];
string LoginPass = Request.Form["login-passwrd"];
// Defines an SQL Connection with our SQL Connection String //
using (SqlConnection conn = new SqlConnection("Valid Connection String Here"))
// Creates a new SQL command that checks the database for a account; notice that '#1' amd '#2' are placeholders //
using (SqlCommand cmd = new SqlCommand("SELECT * FROM AccountData WHERE [User] = #1 AND [Password] = #2", conn))
{
// Replaces the placeholder values in the SQL command with our varaibles that were created from the users input
cmd.Parameters.AddWithValue("#1", LoginUser);
cmd.Parameters.AddWithValue("#2", LoginPass);
// A connection is opened to our SQL Database //
conn.Open();
// Executes the SQL Database reader with the paramaters defined in our SQL Command 'cmd' //
SqlDataReader reader = cmd.ExecuteReader();
// Checks if the SQL reader returned any rows //
if (reader.HasRows)
{
// User Exists //
reader.Close();
System.Diagnostics.Debug.WriteLine("We have found an account");
// Log in the user //
}
else
{
// User Doesnt Exist //
reader.Close();
System.Diagnostics.Debug.WriteLine("No Account Found");
}
// Closes the connection to our SQL Database //
conn.Close();
}
}
I am aware that the code may be vunrable to SQL injection attacks! the website has not been published yet, and security will be added before launch.
I appreciate any help that I receive, if there is anything that doesn't make sense, please let me know!
Thanks for the help everybody! However, i have found a solution to the problem. Inside of the if statement where login details are verified, i added this onto the 'invalid login' return.
ModelState.AddModelError("InvalidLogin", "Invalid login details");
And then, directly below my login form i added the following code
#if (Model.ModelState.ContainsKey("InvalidLogin"))
{
<div class="alert alert-danger">#Model.ModelState["InvalidLogin"].Errors[0].ErrorMessage</div>
System.Diagnostics.Debug.WriteLine("Error message displayed in view");
}
else
{
System.Diagnostics.Debug.WriteLine("No error message to display in view");
}
If you are viewing this post late, looking for an answer, this worked well for me. If you would like help setting this up for your code feel free to # me
I am try to display data from a database. However even though data exists in the database no records are being returned.
If run the following query:
select Id, Movie_Name from [MovieTable] where Movie_Name like '10,000 BC'
I get being returned:
However when running a similar query in c# nothing seems to be being returned. My code is as follows:
try
{
string query = "select * from [MovieTable] where Movie_Name like #MovieName";
string movieName = "10,000 BC"
using (SqlConnection sconnection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=E:\Application\ApplicationDatabase.mdf;Integrated Security=True");)
using (SqlCommand command = new SqlCommand(query, sconnection))
{
sconnection.Open();
command.Parameters.AddWithValue("#MovieName", movieName);
using (SqlDataReader oReader = command.ExecuteReader())
{
if (oReader != null)
{
while (oReader.Read())
{
MessageBox.Show(oReader["Movie_Name"].ToString());
}
}
}
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
The message box never appears. Adding a third message box just above oReader.Read() displays the message "Invalid attempt to read when no data is present". Is there something i am missing?
Your code runs fine for me, with little adaptions though.
You query the value of the attribute 'Year' which is not present in the table and in your first query:
oReader.GetOrdinal("Year")
That causes an exception in the sample.
Single Quotes are not needed since you are using a parametrized query.
For debugging calls to System.Diagnostics.Debug.WriteLine() are more useful than MessageBoxes
Issue was with the data itself. Field was incorrectly set as type "Text". I altered the fields data type to "nvarchar(MAX)". It also mean't the query could be altered to:
"select * from [MovieTable] where Movie_Name = #MovieName"
I'm somewhat new to C# - I have a connection string set in my app web.config called "ApplicationServices" Using C#, how can I write a certain SQL command that retrieves data from my database and set's it to a string that I can operate on?
Here is the full explanation.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx
//Taken from MSDN
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
You can also use an ORM such as LINQ2SQL
http://codesamplez.com/database/linq-to-sql-c-sharp-tutorial
EDIT:
How to debug...
Below are some links on how to use the debugging features in visual studio.
http://msdn.microsoft.com/en-us/library/ms165053.aspx
http://msdn.microsoft.com/en-us/library/k0k771bt(v=vs.71).aspx
http://www.dotnetperls.com/debugging
If you are planning on writing a query that returns one single value, you should have a look at ExecuteScalar. See this example for a quick demo on how to retrieve a value from the database and set it to a variable:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
I have a table of Users (tblUsers) which contains details of University staff. I am trying to populate a text box with the names of lecturers associated with a selected module.
I am getting all UserIDs associated with a particular module, testing if the User is a lecturer, if so then I add the ID to an ArrayList.
I then iterate through this array and call the method below during each iteration passing through the current ID.
However, if you look at the method below I am using a SqlDataReader and am getting an error while reading from it on this line:
txtLecturerName.Text += myReader["First_Name"].ToString();
The error message is:
'myReader["First_Name"]' threw an exception of type 'System.IndexOutOfRangeException'
The table layout I am using is below the method code. Any help with this would be greatly appreciated, I am one cup of coffee away from putting my head through the screen.
public void outputLecturerNames(string lecturerID)
{
// Create a new Connection object using the connection string
SqlConnection myConnection = new SqlConnection(conStr);
// If the connection is already open - close it
if (myConnection.State == ConnectionState.Open)
{
myConnection.Close();
}
// 'using' block allows the database connection to be closed
// first and then the exception handling code is triggered.
// This is a better approach than using a 'finally' block which
// would close the connection after the exception has been handled.
using (myConnection)
{
try
{
// Open connection to DB
myConnection.Open();
SqlCommand selectCommand = new SqlCommand(selectQuery, myConnection);
// Declare a new DataReader
SqlDataReader myReader;
selectQuery = "SELECT * FROM tblUsers WHERE User_ID='";
selectQuery += lecturerID + "'";
myReader = selectCommand.ExecuteReader();
while (myReader.Read())
{
txtLecturerName.Text += myReader["First_Name"].ToString();
txtLecturerName.Text += " ";
txtLecturerName.Text += myReader["Last_Name"].ToString();
txtLecturerName.Text += " , ";
}
myReader.Close();
}
catch (Exception err)
{
Console.WriteLine("Error: " + err);
}
}
}
tblUsers:
[User_ID][First_Name][Last_Name][Email_Address]
In your method, the variable selectQuery is not declared, and it is used as parameter to SqlCommand before it is assigned the query string on tblUsers.
You've probably misspelled a column name.
In general, you should never write SELECT * FROM ....
Instead, you should select only the columns you need.
This will make your program run faster by only querying the information that you need, and can produce better error messages.
This error is created when the column name given is not found. If you are anything like me, you've probably checked it several times, but is the table name correct (correct database, correct schema) and is the column name correct?
http://msdn.microsoft.com/en-us/library/f01t4cfy.aspx
You might try fully qualifying the name of the table (database.dbo.tblUsers). This would ensure that you are hitting the table you think you are. Also, try and put the names of the columns into the SQL statement. If they are not correct, your SQL statement will not execute properly.
When several fields in a MSAccess table need to be updated (For instance Salary=Salary*Factor, SomeNumber=GetMyBusinessRuleOn(SomeNumber) etc...),and the update should affect every record in a table, which technique would you use?
I have just started to implement this with DataSets, but got stuck (Updating and persisting dataset problem)
But maybe this isn't even the ideal way to handle this kind of batch update?
Note : the updates don't have to be on disconnected data first, so a dataset is not necessary.
UPDATE :
One command won't do, I need some kind of recordset or cursor to cycle through the records
I would just use a ODBCConnection/ODBCCommand and use a SQL Update query.
There is a JET Database driver that you should be able to use to establish a database connection to a MSAccess database using the ODBCConeection object.
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\\PathTo\\Your_Database_Name.mdb; User Id=admin; Password=";
using (OdbcConnection connection =
new OdbcConnection(connectionString))
{
// Suppose you wanted to update the Salary column in a table
// called Employees
string sqlQuery = "UPDATE Employees SET Salary = Salary * Factor";
OdbcCommand command = new OdbcCommand(sqlQuery, connection);
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// The connection is automatically closed when the
// code exits the using block.
}
You could use these websites to help you generate a connection string:
http://www.connectionstrings.com/
http://www.sqlstrings.com/
EDIT - Example for using a data reader to cycle through records in order to aply the business rule
I should note that the following example could be improved in certain ways (especially if the database driver supports parameterized queries). I only wanted to give a relatively simple example to illustrate the concept.
using (OdbcConnection connection =
new OdbcConnection(connectionString))
{
int someNumber;
int employeeID;
OdbcDataReader dr = null;
OdbcCommand selCmd = new OdbcCommand("SELECT EmployeeID, SomeNumber FROM Employees", connection);
OdbcCommand updateCmd = new OdbcCommand("", connection);
try
{
connection.Open();
dr = selCmd.ExecuteReader();
while(dr.Read())
{
employeeID = (int)dr[0];
someNumber = (int)dr[1];
updateCmd.CommandText = "UPDATE Employees SET SomeNumber= " + GetBusinessRule(someNumber) + " WHERE employeeID = " + employeeID;
updateCmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Don't forget to close the reader when we're done
if(dr != null)
dr.Close();
}
// The connection is automatically closed when the
// code exits the using block.
}
Sounds like you just need an update statement:
http://msdn.microsoft.com/en-us/library/bb221186.aspx
You can use the OleDb Provider for this.