This is going to take some explaining. I'm new to ASP, having come from PHP. Completely different world. Using the MySql Connecter/Net library, I decided to make a database wrapper which had a fair amount of fetch methods, one being a "FetchColumn()" method which simply takes a string as its parameter and uses the following implementation:
public object FetchColumn(string query)
{
object result = 0;
MySqlCommand cmd = new MySqlCommand(query, this.connection);
bool hasRows = cmd.ExecuteReader().HasRows;
if (!hasRows)
{
return false;
}
MySqlDataReader reader = cmd.ExecuteReader();
int count = 0;
while(reader.HasRows)
{
result = reader.GetValue(count);
count++;
}
return result;
}� return result;
}public object FetchColumn(string query)
What I'm looking for is a way to return false IF and only IF the query attempts to fetch a result which doesn't exist. The problem is that, with my implementation, it throws an error/exception. I need this to "fail gracefully" at run time, so to speak. One thing I should mention is that with this implementation, the application throws an error as soon as the boolean "hasRows" is assigned. Why this is the case, I have no idea.
So, any ideas?
It's hard to say for sure, since you didn't post the exact exception that it's throwing, but I suspect the problem is that you're calling ExecuteReader on a command that is already in use. As the documentation says:
While the MySqlDataReader is in use, the associated MySqlConnection is busy serving the MySqlDataReader. While in this state, no other operations can be performed on the MySqlConnection other than closing it. This is the case until the MySqlDataReader.Close method of the MySqlDataReader is called.
You're calling cmd.ExecuteReader() to check to see if there are rows, and then you're calling ExecuteReader() again to get data from the rows. Not only does this not work because it violates the conditions set out above, it would be horribly inefficient if it did work, because it would require two trips to the database.
Following the example shown in the document I linked, I'd say what you want is something like:
public object FetchColumn(string query)
{
MySqlCommand cmd = new MySqlCommand(query, this.connection);
MySqlDataReader reader = cmd.ExecuteReader();
try
{
bool gotValue = false;
while (reader.Read())
{
// do whatever you're doing to return a value
gotValue = true;
}
if (gotValue)
{
// here, return whatever value you computed
}
else
{
return false;
}
}
finally
{
reader.Close();
}
}
I'm not sure what you're trying to compute with the HasRows and the count, etc., but this should get you pointed in the right direction.
you need to surround the error throwing code with a try clause
try {
//The error throwing Code
}
catch (exception e)
{
//Error was encountered
return false
}
If the error throwing code throws and error the catch statement will execute, if no error is thrown then the catch statement is ignored
First of all do a try and catch
try
{
//code
}
catch (Exception exp)
{
//show exp as message
}
And the possible reason of your error is that your mysql query has errors in it.
try executing your query directly in your mysql query browser and you'll get your answer.
If its working fine then double check your connection string if its correct.
NOTE:mark as answer if it solves your issue
Related
I have a class function where I'm trying to read data from a database table using the SqlDataReader. When the SqlCmd.ExecuteReader() is called, I see(upon debugging) that the resultView of the SqlDataReader says "Enumeration yielded no results". However, the SqlDataReader.Read() still returns true and therefore enters the while() code block.
The query executes correctly on SQL, and even changing the query to get data from other tables give the same results. Please note that I have several other functions in a separate class executing the similar code to get data from these same database tables and they work without any issue.
Another observation is that after the ExecuteReader() is called, the VisibleFieldCount field of the SQLDataReader has the value = 11, which is equal to the total number of columns in the Customer table. This suggests that the reader is able read atleast some of the data from the database.
Any suggestions or help will be appreciated. Please let me know if any more information is required.
I have tried simplifying the function code as much as possible by removing any code logic other than the data retrieval part for the ease of debugging.
public bool MatchPassword(string username, string enteredPassword)
{
bool loginSuccessful = false;
string returnedpasswordbinary;
DatabaseConnection databaseConnectionObj = new DatabaseConnection();
databaseConnectionObj.CreateDBConnection(); //Sets the connection string and opens database connection
string query = "SELECT * FROM dbo.Customers WHERE CustomerID='ALFKI';";
SqlCommand sqlCommandObj = new SqlCommand();
sqlCommandObj.CommandText = query;
sqlCommandObj.Connection = databaseConnectionObj.SqlConnectionObj1;
try
{
SqlDataReader sqlDataReaderObj = sqlCommandObj.ExecuteReader();
if (sqlDataReaderObj.HasRows)
{
while (sqlDataReaderObj.Read())
{
returnedPasswordBinary = sqlDataReaderObj[0].ToString();
}
}
}
catch (Exception ex)
{
throw ex;
}
return loginSuccessful;
}
Can you please set commandtype
command.CommandType = CommandType.Text;
I want to declare a MySqlDataReader, without initialising it or assigning any value to it. Like the code below.
MySqlDataReader rdr;
try
{ /* stuff to open the MySqlDataReader and use it, not important for my question */ }
catch (Exception e)
{ /* error handling stuff, not important for my question */ }
finally
{
/* code to close the reader when things have gone wrong */
try
{
if (rdr != null)
{
if (rdr.IsClosed == false)
{
rdr.Close();
}
}
}
catch (Exception e)
{ /* error handling stuff, not important for my question */ }
}
The reason for that is I want to close the MySqlDataReader in a finally section of the try if it does in fact I do get a run time error. So the MySqlDataReader has to be declared before of the try, otherwise it'll be out of scope for the finally code.
However when I compile the code above I get the compile time error "Use of unassigned local variable 'rdr'" so I want to set it to something for example
MySqlDataReader rdr = New MySqlDataReader();
But this give me a compile time error "The type 'MySql.Data.MySqlClient.MySqlDataReader' has no constructors defined". And assigning the result of a command object will make the code compile however that can go wrong and is what my try is trying to catch.
When this function is called for a second time if the MySqlDataReader object is not closed from the first iteration, then it will crash second time around.
So how do I clean up my MySqlDataReader objects when things go wrong?
Just assign it with null. The compiler will know a value has assigned, although it is null.
MySqlDataReader rdr = null;
In your finally block, check on the null value.
MySqlDataReader rdr = null;
try
{
... // do stuff here
}
finally
{
if (rdr != null)
{
// cleanup
}
}
Or use using if possible. It will cleanup rdr for you:
using (MySqlDataReader rdr = ... )
{
}
One option is to initialize it to null to start with:
MySqlDataReader rdr = null;
After all, you're already checking whether it's null within the finally block in your sample code, so that's fine.
It's not clear why you're not just using a using statement though. You can always put a try/catch inside (or outside) that.
I have some problems with my database connection in my application.
My application stores some data into a mysql database and now I got the error mentioned in the title.
The problem is:
Right before I call the method that throws this exception I call another method which also connects to the database but successfully.
At first I thought that there is an error in my source but there is no error.
Here is the bad method:
public static bool checkExistence(object obj)
{
MySqlCommand checkQuery = new MySqlCommand(MySQLQueries.getCheckQueryByObject(obj), connection);
object checkResult = null;
if (connection.State == System.Data.ConnectionState.Closed)
{
OpenConnection();
try
{
checkResult = checkQuery.ExecuteScalar();
}
catch (MySqlException ex)
{
ErrorHandler(ex);
return true;
}
catch (Exception ex)
{
ErrorHandler(ex);
return true;
}
finally
{
CloseConnection();
}
}
else
{
checkResult = checkQuery.ExecuteScalar();
}
if (checkResult != null)
return true;
else
return false;
}
As you can see I first create a new command which later will check if an object exists.
The result of the query will be stored in object checkResult and at the end I simply check if checkResult == null.
Because of some problems with opening / closing the connection I decided to check if the connection is opened or not.
Now if the bad method is called the connection is closed.
Then after calling OpenConnection() the connection is opened again with the same settings as before.
As soon as the application executes checkResult = checkQuery.ExecuteScalar(); the exception is thrown.
I really don't know what actually is the problem.
To ensure that the connection is valid from my point of view I put connection into the watchlist and tracked every change made to it by the application.
Nothing was different than in any other method that successfully used the database.
A friend of mine said that there might be a kind of optimization error while building the application.
He himself doesn't work with C# but sometime with C so it was just a vague guess.
Is there maybe any error in the code that I missed or any guess why this happens?
Thanks in advance!
Greetz
Edit: I use the latest version of MySQL's C# connector
A fairly large web application written in C# keeps throwing up 2 errors:
'ExecuteReader requires an open and available Connection. The connection's current state is open.'
and
'Invalid attempt to call Read when reader is closed.'
These errors were sporadic -- the pages used to load fine about 95% of the time, but recently they've become endemic, they're occurring all the time and basically crippling the application's functionality.
The web app is highly reliant on an MS SQL database, and the errors appear to not be confined to just one page, but nearly all the pages that connect to the database.
The queries are performed as such:
Database.Open(); // Custom class that has our connection string hard coded.
string query = "SELECT * FROM table"; // (dummy query)
SqlCommand command = new SqlCommand(query, Database.Conn);
SqlDataReader reader = null;
try {
reader = command.ExecuteReader(CommandBehaviour.CloseConnection);
if (reader.HasRows) {
while (reader.Read()) {
// Do something with the data.
}
}
reader.Close();
}
catch (Exception e) {
throw new Exception(e.Message);
}
finally {
if (reader != null) {
reader.Close();
}
}
I've researched these errors on the web and I've seen a few potential solutions that I've tried to no avail:
Putting various parts of the code in a using() block.
Specifying CommandBehaviour.CloseConnection for the reader.
Checking that MARS is enabled.
Ensuring that a new connection object is created each time.
I've spent ages searching for solutions to this, not to mention a long long time trying to make it work, and I'm almost on the verge of pulling my hair out now!
Please help!
EDIT -- Fixed the problem, see the comments section.
It looks to me that Database is a type and not an instance.
You are running into multithreading issues now.
You have 2 options:
Apply the [ThreadStatic] to the field containing the connection object created by Database.Open()
or
Make Database.Open() return a fresh instance of the connection object and use that when constructing the command
In addition to leppie's answer, you should also be Dispose()ing of any IDisposable types:
try
{
Database.Open(); // Custom class that has our connection string hard coded.
string query = "SELECT * FROM table"; // (dummy query)
using (SqlCommand command = new SqlCommand(query, Database.Conn))
using (SqlDataReader reader = command.ExecuteReader(CommandBehaviour.CloseConnection))
{
if (reader.HasRows)
{
while (reader.Read())
{
// Do something with the data.
}
}
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
I have a C# database layer that with static read method that is called every second in background timer.
currently I create SqlCommand, SqlConnection once as a class memeber.
In every method call I execute the command to get the results,I am doing so to avoid creation of connection and command every second, but I am afraid from exception occurs in this method that will break the connection or put the object in the invalid state.
This is my current implementation (Timer Handler)
static void GetBarTime(object state)
{
lock (_staticConnection)
{
SqlDataReader dataReader = null;
try
{
dataReader = _getMaxTimeCommand.ExecuteReader();
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
catch (Exception ex)
{
//Log the error
}
finally
{
dataReader.Dispose();
}
}
}
What is the best practise?
MORE DETAILS:
I am doing this in a timer as there is another prorcess update my table every second, and there is another exposed method used by set of clients and called every second to get the latest value.
So instead of executing select statement every second for each client, I am doing it in a timer and update global variable that is used by the clients.
SqlConnection has pooling built in; you would see almost no difference if you used:
using(SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
// your code
}
each time. And that can react automatically to dead (underlying) connections.
Currently you have a bug, btw; if the command fails, the reader will still be null... either check for null before calling Dispose():
if(dataReader !=null) {dataReader.Dispose();}
or just use using:
try
{
using(SqlDataReader dataReader = _getMaxTimeCommand.ExecuteReader())
{
dataReader.Read();
_currentTick = dataReader.GetInt32(0);
}
}
catch (Exception ex)
{
//Log the error
}
It can be pretty difficult to find out if an execption means that the connection is a dead duck. To be on the safe side, you could close and reopen the SqlConnection and SqlCommand whenever you encounter an exception, just in case. That doesn't cause any overhead when everything works alright.