Check if datareader is null or has no rows? ASP.NET - c#

So I took over this project and one page is throwing a lot of errors. I would need to refactor the whole thing but as always time is an issue.
In one case the code check's whether a datareader has any rows and if not go to an error page. However as the code is now the datareader can be null (didn't successfully connect to db) and in those cases I can't use
if (!dr.HasRows)
//
becasuse it obviously gives me 'nullreferenceexception was unhandled by code'. I tried with !dr.Read but same thing.
A part of the code is something like
SqlDataReader dr = null;
try
{
//connect to db etc
dr = DbHelper.GetReader("sp_GetCustomer", param);
}
catch
{
//show an error message
}
// and then:
if (!dr.HasRows)
{
}
Any suggestions?
Thanks in advance.

What about:
if (dr == null || !dr.HasRows) {
// Do something
}

One possibility is:
SqlDataReader dr = null;
try
{
//connect to db etc
dr = DbHelper.GetReader("sp_GetCustomer", param);
if (!dr.HasRows)
{
}
}
catch
{
//show an error message
}

Related

Postgresql query returns NullReferenceException

I'm using Selenium + postgre integration in order to validate correct data on database. After an action on UI then I'm using Npgsql library in order to receive scalar value from cell and then use it for assertion.
Code looks line:
public static string GetCreditAmount(string orderId, string accountNumber)
{
string findCreditQuery = $#"SELECT ""Credit"" FROM accounting.""AccountLines"" al INNER JOIN accounting.""Accounts"" acc ON al.""Account_FK"" = acc.""Id""
WHERE
""OrderId"" = '{orderId}'
AND ""AccountNumber"" = '{accountNumber}'
ORDER BY al.""CreatedDateUtc"" DESC";
using (var connection = new NpgsqlConnection(Configuration.AdminConnectionString))
{
connection.Open();
var transaction = connection.BeginTransaction();
try
{
var account = connection.ExecuteScalar(findCreditQuery).ToString();
return account;
}
catch (NullReferenceException e)
{
Thread.Sleep(3000);
var account = connection.ExecuteScalar(findCreditQuery).ToString();
return account;
}
catch (Exception e)
{
transaction.Rollback();
throw e;
}
}
}
The problem which I'm receiving is NullReferenceException, however results are really random. In one test I'm firing & asserting few times where in like 85% it does not work (Null reference) and from time to time in like 15% it works (test passed). Strange case is that assertion which was fine in one run fails in another one.
I was trying to add static sleeps (Thread.Sleep) in order to give database few extra second for proceeding but all it still fails.
Is there any proper solution which can be used?
If you do this:
object o = null;
string s = o.ToString();
I believe you will get the same error. I believe the issue is your database object is null.
This will probably fix it:
object o = connection.ExecuteScalar(findCreditQuery);
string account = o == null ? null : o.ToString();
Alternatively, you can implement a DbDataReader and use the IsDbNull method. It will be more work but might also be more scalable if you plan to do more than what's currently being done:
string account;
using (NpgsqlCommand cmd = new NpgsqlCommand(findCreditQuery, connection))
{
using (NpgsqlDataReader reader = cmd.ExecuteReader())
{
reader.Read();
if (!reader.IsDBNull(0))
account = reader.GetString(0);
}
}

SqlCommand.ExecuteReader() does not throw SqlException when deadlocked

We're using C# SqlCommand.ExecuteReader() to issue SQL Server stored procedure and SQL requests inside a transaction.
When the connection is chosen as a deadlock victim, ExecuteReader() does NOT throw SqlException with 1205 deadlock code for some commands but DOES for others.
According to MSDN
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Considering that we use SqlCommand object encapsulated inside our own database request framework, is there a way to always guarantee that the exception is thrown when a deadlock occurs?
We're using .Net 4.5, SQL Server 2008 R2, Visual Studio 2012
Here is a simplified version of our database access framework code:
SqlDataReader DoWork( string sql ) {
...
cmd = new SqlCommand( sql );
SqlDataReader rdr = null;
try {
rdr = cmd.ExecuteReader( CommandBehavior.Default );
} catch (SqlException sqle) {
// Log the error, throw a custom exception, etc.
// if (sqle.ErrorCode == 1205) ...
...
if (rdr != null) {
rdr.Close();
rdr = null;
}
}
// All is well, so just return to caller to consume the result set
return rdr;
}
...
main() {
...
SqlDataReader result = DoWork( "select ...";
if (result.HasRows) { // Check there is data to read...
while (result.Read()) {
...
}
result.Close();
...
}
I don't know why you are doing this:
if (result.HasRows)
This is not necessary and it prevents the deadlock from appearing:
If a transaction is deadlocked, an exception may not be thrown until Read is called.
Delete that if. It's a common anti pattern. It's often introduced by people who copy sample code without really understanding what it does.
This in your catch is also an anti pattern:
if (rdr != null) {
rdr.Close();
rdr = null;
}
Just use using.
this is the code from that link, Stack wouldnt allow it as an answer
function DoWork() {
using (TransactionScope scope = new TransactionScope(...)) {
cmd = new SqlCommand("select ...");
using (DataReader rdr = cmd.ExecuteReader ()) {
while(rdr.Read()) {
... process each record
}
}
scope.Complete ();
}
}

declaring a MySqlDataReader without initialising it

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.

C# Code Not Executing

I have a C#/WPF application with a tabbed interface that has been behaving strangely. After thinking originally my problems were related to the TabControl, I now believe that it's something different and I'm completely stuck. The following method is just supposed to pull some data out of the database and load a couple of WPF ComboBoxes. The strange thing is that the code reaches a certain point, specifically the end of the loop that loads cboState's Item collection, and then continues on. No code placed below that loop executes, no errors are thrown than I can find or see, and no breakpoints placed below that loop ever get reached. I'm completely perplexed.
private void loadNewProjectTab() {
dpDate.SelectedDate = DateTime.Now;
cboProjectType.Items.Add("Proposal");
cboProjectType.Items.Add("Pilot");
cboProjectType.SelectedIndex = -1;
string sql = "SELECT State FROM States ORDER BY ID";
OleDbCommand cmd = new OleDbCommand(sql, connection);
if(connection.State == ConnectionState.Closed) {
connection.Open();
}
OleDbDataReader reader = cmd.ExecuteReader();
while(reader.HasRows) {
reader.Read();
cboState.Items.Add(reader["State"].ToString().Trim());
} // <-- Nothing below here executes.
connection.Close();
}
while(reader.HasRows) {
reader.Read();
cboState.Items.Add(reader["State"].ToString().Trim());
}
reader.HasRows will return true even after you've read all the rows and moved past the last one with reader.Read(); at that point, you'll get an exception on reader["State"].
Since reader.Read() returns a boolean to indicate whether there's a current row, you should skip calling reader.HasRows entirely:
while(reader.Read()) {
cboState.Items.Add(reader["State"].ToString().Trim());
}
Um I think is wrong your loop it should be.
if (reader.HasRows)
{
while(reader.Read())
{
cboState.Items.Add(reader["State"].ToString().Trim());
}
}
Note that the bucle is with while(reader.Read())
This is your problem:
while(reader.HasRows) {
reader.Read();
cboState.Items.Add(reader["State"].ToString().Trim());
}
HasRows indicates whether or not the reader retrieved anything; it doesn't change as you read through it (in other words, it's not analogous to an end-of-file indicator like you're using it). Instead, you should do this:
while(reader.Read()) {
cboState.Items.Add(reader["State"].ToString().Trim());
}
Reader should be closed.
using(var reader = cmd.ExecuteReader())
{
if(reader.HasRows)
{
while(reader.Read())
{
cboState.Items.Add(reader["State"].ToString().Trim());
}
}
}

Workaround for ASP throwing MySQL exception

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

Categories