All code after SqlDataReader.ExecuteReader skipped - c#

I have the following function:
private void populate()
{
String connectionString = Properties.Settings.Default.Database;
String selectString = "select artikelnummer, omschrijving from Artikels";
SqlDataReader reader = null;
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(selectString);
reader = command.ExecuteReader();
connection.Open();
int x = 0;
while (reader.Read())
{
String item = String.Empty;
item = Convert.ToString(reader["Artikelnummer"]) + "\t" + Convert.ToString(reader["Omschrijving"]);
x++;
listboxGeselecteerd.Items.Add(item);
}
}
Everything that follows after reader = command.ExecuteReader(); is skipped.
Is there anything I've done wrong?
UPDATE: Moved the connection.Open(); to the right spot. Now, when I reach that line, my output shows Step into: Stepping over non-user code 'System.Data.SqlClient.SqlConnection.Open
And then skips the rest of the function.

My money is on a method higher up in the call stack eating the exception because this should've thrown one because the connection hadn't been opened. That's your biggest problem.
The next problem you have is that your connection is not associated with the SqlCommand so even if it were opened, it wouldn't matter.
Finally, connection.Open(); needs to be before ExecuteReader.
In addition to that, you really ought to be using using blocks.
{
String connectionString = Properties.Settings.Default.Database;
String selectString = "select artikelnummer, omschrijving from Artikels";
SqlDataReader reader = null;
using (SqlConnection connection = new SqlConnection(connectionString))
/* you also need to associate the connection with the command */
using (SqlCommand command = new SqlCommand(selectString, connection))
{
connection.Open();
reader = command.ExecuteReader();
int x = 0;
while (reader.Read())
{
String item = String.Empty;
item = Convert.ToString(reader["Artikelnummer"]) + "\t" + Convert.ToString(reader["Omschrijving"]);
x++;
listboxGeselecteerd.Items.Add(item);
}
}
}
How about some simple "printf"-style debugging and posting the exception you get?
try
{
connection.Open();
...
}
//catch (Exception e)
catch (SqlException e)
{
// at least one of these..
Console.WriteLine(e);
MessageBox.Show(e);
Debug.WriteLine(e);
var inner = e.InnerException;
while (inner != null)
{
//display / log / view
inner = inner.InnerException;
}
}
Given the exception text from the comments (A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll) looks more like the message you'd get just before the real message showed up, I would catch a SqlException and examine the InnerException(s).

I'm surprised it's not throwing an exception, but you need to open the connection before you execute your reader.

You have to open the connection before you try to use it. Move connection.Open() above your command.ExecuteReader() call.

I can only surmise that you need to open your connection before you execute the reader, and that it's being skipping because an exception is being thrown.

You need to open the connection before you call ExecuteReader.
Also, you don't assign your connection to the SqlCommand. You need to do it like this:
using(qlConnection connection = new SqlConnection(connectionString))
{
using(SqlCommand command = new SqlCommand(selectString,connection))
{
connection.Open();
reader = command.ExecuteReader();
// rest of your code.
}
}

private void populate(){
String connectionString = Properties.Settings.Default.Database;
String commandString = "SELECT artikelnummer, omschrijving FROM Artikels";
using (SqlConnection cn = new SqlConnection(connectionString)){
using (SqlCommand cm = new SqlCommand(commandString, cn)){
cn.Open();
SqlDataReader dr = cm.ExecuteReader();
int x = 0;
while (dr.Read()){
String item = String.Empty;
item = Convert.ToString(dr["Artikelnummer"]) + "\t" + Convert.ToString(dr["Omschrijving"]);
x++;
listboxGeselecteerd.Items.Add(item);
}
}
}
}
On a side note, what are you doing with the 'int x'? I see you are incrementing it, but not doing anything with it.

Related

Having trouble with: The connection was not closed. The connection's current state is open. - SQL Server & C#

I'm currently working on the login form of a school management system. The thing is that when I try to log in, I get an error:
System.InvalidOperationException: The connection was not closed. The connection's current state is open
It says that the error is on the 30th line of code but I can't seem to find a way to solve it.
Here's the code of the method in which the error occurs:
public void LoginTeacher()
{
try
{
command = new SqlCommand("TeacherLogin", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open(); // This is the 30th line.
command.Parameters.AddWithValue("#username", Txt_User.Text);
command.Parameters.AddWithValue("#password", Txt_Pass.Text);
SqlDataReader dataReader = command.ExecuteReader();
if (dataReader.Read())
{
TeacherDash teacherDash = new TeacherDash();
this.Hide();
teacherDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString();
teacherDash.ShowDialog();
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
connection.Close();
}
}
Immediately after that error is shown there is another one that says:
System.InvalidOperationException: Invalid attempt to call CheckDataIsReady when reader is closed
and points to line 71 which is the following:
public void Login()
{
try
{
command = new SqlCommand("SP_USER_LOGIN", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
command.Parameters.AddWithValue("#user", Txt_User.Text);
command.Parameters.AddWithValue("#pass", Txt_Pass.Text);
SqlDataReader dataReader = command.ExecuteReader();
if (dataReader.Read())
{
LoginTeacher();
if (dataReader[10].Equals("Admin"))
{
AdminDash adminDash = new AdminDash();
this.Hide();
adminDash.lblusertype.Text = dataReader[1] + " " + dataReader[2].ToString();
adminDash.ShowDialog();
this.Close();
}
There's more code after that but I don't find it relevant since it's the same thing but with the different type of users.
Thanks in advance!
You could try changing your TeacherLogin() method to something like the following:
public void TeacherLogin()
{
try
{
using(SqlConnection con = new SqlConnection("connection string"))
{
using(SqlCommand cmd = new SqlCommand("TeacherLogin"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#username", Txt_User.Text);
cmd.Parameters.AddWithValue("#password", Txt_Pass.Text);
cmd.Connection = con;
con.Open();
using(SqlDataReader dr = cmd.ExecuteReader())
{
while(dr.Read())
{
TeacherDash teacherDash = new TeacherDash();
this.Hide();
teacherDash.lblusertype.Text = string.Format("{0} {1}", dr[1], dr[2]);
teacherDash.ShowDialog();
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
There's no need to use finally{} to close the connection as its all wrapped in a using() block, it will close and dispose on its own when the code leaves the block. I'd always recommend using SQL connections and commands in this way as not doing so can cause issues by leaving connections open.
Database object need to be closed and disposed. Keeping them local to the method where they are used lets you make sure this happens. using blocks take care of this for you.
I used a DataTable instead of testing with the reader because the connection must remain open as long as the reader is in use. Opening and closing the connection in the briefest possible time is important.
Please don't use .AddWithValue. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
Of course you will have to check your database for the real datatypes and field size to have the correct .Add method.
public void LoginTeacher()
{
DataTable dt = new DataTable();
using (SqlConnection cn = new SqlConnection("your connection string"))
using (SqlCommand cmd = new SqlCommand("TeacherLogin", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#username",SqlDbType.VarChar,100 ).Value = Txt_User.Text;
cmd.Parameters.Add("#password",SqlDbType.VarChar, 100 ).Value =Txt_Pass.Text;
cn.Open();
dt.Load(cmd.ExecuteReader());
} //Your connection and command are both disposed
if (dt.Rows.Count > 0)
{
TeacherDash teacherDash = new TeacherDash();
teacherDash.lblusertype.Text = $"{dt.Rows[0][1]} {dt.Rows[0][2]}";
teacherDash.ShowDialog();
Close();
}
else
MessageBox.Show("Sorry, login failed");
}

How do I check whether a value is 1 or 0 in SQL?

So I've setup my database connection and it does connect.
Now I want to check each row in my table whether the column isactivated is either 0 or 1 because it's a bit but I don't know how to do it.
Would I execute a query? Would I store all the rows in a list and then check?
using (var connection = new SqlConnection(cb.ConnectionString))
{
try
{
connection.Open();
if (connection.State == ConnectionState.Open)
{
Console.WriteLine("Connected!");
}
else
{
Console.WriteLine("Failed..");
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
SqlCommand command = new SqlCommand("SELECT column FROM table", connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// 0 = false, 1 = true,
bool result = (bool)reader[0];
//... do whatever you wanna do with the result
}
I think you are looking for something like this:
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "SELECT * FROM Customers";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
sqlConnection1.Close();
Taken from msdn-lib.
In the SqlDataReader should be all your data including your isactivated column, which you then can check for its respective values.
If you want to read the field you can implement something like this:
using (var connection = new SqlConnection(cb.ConnectionString)) {
try {
connection.Open();
// connection.Open() either succeeds (and so we print the message)
// or throw an exception; no need to check
Console.WriteLine("Connected!");
//TODO: edit the SQL if required
string sql =
#"select IsActivated
from MyTable";
using (var query = new SqlCommand(sql, connection)) {
using (var reader = query.ExecuteReader()) {
while (reader.Read()) {
// Now it's time to answer your question: let's read the value
// reader["IsActivated"] - value of IsActivated as an Object
// Convert.ToBoolean - let .Net do all low level work for you
bool isActivated = Convert.ToBoolean(reader["IsActivated"]);
// Uncomment, if you insist on 0, 1
// int bit = Convert.ToInt32(reader["IsActivated"]);
//TODO: field has been read into isActivated; put relevant code here
}
}
}
}
catch (DataException e) { // Be specific: we know how to process data errors only
Console.WriteLine(e);
throw;
}
}

How can I get SQL result into a STRING variable?

I'm trying to get the SQL result in a C# string variable or string array. Is it possible? Do I need to use SqlDataReader in some way?
I'm very new to C# functions and all, used to work in PHP, so please give a working example if you can (If relevant I can already connect and access the database, insert and select.. I just don't know how to store the result in a string variable).
This isn't the single greatest example in history, as if you don't return any rows from the database you'll end up with an exception, but if you want to use a stored procedure from the database, rather than running a SELECT statement straight from your code, then this will allow you to return a string:
public string StringFromDatabase()
{
SqlConnection connection = null;
try
{
var dataSet = new DataSet();
connection = new SqlConnection("Your Connection String Goes Here");
connection.Open();
var command = new SqlCommand("Your Stored Procedure Name Goes Here", connection)
{
CommandType = CommandType.StoredProcedure
};
var dataAdapter = new SqlDataAdapter { SelectCommand = command };
dataAdapter.Fill(dataSet);
return dataSet.Tables[0].Rows[0]["Item"].ToString();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
if (connection != null)
{
connection.Close();
}
}
}
It can definitely be improved, but it would give you a starting point to work from if you want to go down a stored procedure route.
Try This:
SqlConnection con=new SqlConnection("/*connection string*/");
SqlCommand SelectCommand = new SqlCommand("SELECT email FROM table1", con);
SqlDataReader myreader;
con.Open();
myreader = SelectCommand.ExecuteReader();
List<String> lstEmails=new List<String>();
while (myreader.Read())
{
lstEmails.Add(myreader[0].ToString());
//strValue=myreader["email"].ToString();
//strValue=myreader.GetString(0);
}
con.Close();
accessing the Emails from list
lstEmails[0]->first email
lstEmails[1]->second email
...etc.,
You could use an SQL Data Reader:
string sql = "SELECT email FROM Table WHERE Field = #Parameter";
string variable;
using (var connection = new SqlConnection("Your Connection String"))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Parameter", someValue);
connection.Open();
using (var reader = command.ExecuteReader())
{
//Check the reader has data:
if (reader.Read())
{
variable = reader.GetString(reader.GetOrdinal("Column"));
}
// If you need to use all rows returned use a loop:
while (reader.Read())
{
// Do something
}
}
}
Or you could use SqlCommand.ExecuteScalar()
string sql = "SELECT email FROM Table WHERE Field = #Parameter";
string variable;
using (var connection = new SqlConnection("Your Connection String"))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Parameter", someValue);
connection.Open();
variable = (string)command.ExecuteScalar();
}
This May help you For MySQL
MySqlDataReader reader = mycommand.ExecuteReader();
while (reader.Read())
{
TextBox2.Text = reader.ToString();
}
For SQL
using (SqlCommand command = new SqlCommand("*SELECT QUERY HERE*", connection))
{
//
// Invoke ExecuteReader method.
//
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
TextBox2.Text = reader.GetString(0);
}
}
Try this:
public string SaveStringSQL(string pQuery, string ConnectionString)
{
var connection = new Conexao(ConnectionString);
connection.Open();
SqlCommand command = new SqlCommand(pQuery, connection.Connection);
var SavedString = (string)command.ExecuteScalar();
connection.Close();
return SavedString;
}
The ExecuteScalar function saves whatever type of data there is on your database - you just have to specify it.
Keep in mind that it can only save one line at a time.

Returning the SqlDataReader

I am trying to either pass a reader by reference or to have one returned. And I am having issues with it on the return.
public static SqlDataReader GetSql(string businessUnit, string taskId)
{
const string connstring = "Connection string";
SqlConnection conn = new SqlConnection(connstring);
SqlCommand command = new SqlCommand();
SqlDataReader reader;
try
{
conn.Open();
command.Connection = conn;
command.CommandType = CommandType.Text;
command.CommandText =
"SELECT * FROM Audits WHERE BusinessUnit = #BU AND TaskID = #TID";
command.Parameters.AddWithValue("#BU", businessUnit);
command.Parameters.AddWithValue("#TID", taskId);
return reader = command.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
return null;
}
finally
{
conn.Close();
}
}
SqlDataReader reader = QaqcsqlLib.GetSql("job", "Task1");
if (reader.HasRows)
{
while (reader.Read())
MessageBox.Show(reader[0].ToString());
}
but I get the following error
Invalid attempt to call HasRows when reader is closed.
Any Ideas?
This is the problem:
finally
{
conn.Close();
}
You're closing the connection before the method returns. The reader isn't going to be able to function without an open connection.
(It's not clear why you've got the reader variable at all, given that you only use it when returning.)
Returning a SqlDataReader in a method which itself opens the connection is generally tricky - because it means you don't have a nice way of closing the connection. Better would be to let the caller pass in the connection, at which point you can have:
using (var connection = new SqlConnection(...))
{
using (var reader = QaqcsqlLib.GetSql(connection, "job", "Task1"))
{
// Use the reader here
}
}
EDIT: As noted by Scott, your use of CommandBehavior.CloseConnection would allow closing the reader to close the connection. However, it makes other things trickier. For example, you'd have to dispose of the connection if an exception occurs (because then the caller won't have a chance), but not otherwise - I still prefer my approach.
John is right about why you are having the problem but you don't need to pass in a connection.
I can see that you are already using the SqlCommand.ExecuteReader(CommandBehavior) overload when you start your reader and passing in CommandBehavior.CloseConnection. However the thing you are doing wrong is you are never disposing of the reader that is returned from your function. Remove the finally block then wrap your returned reader in a using block. This will close the underlying connection for you when you exit the block (becuse you passed in CommandBehavior.CloseConnection)
using(SqlDataReader reader = QaqcsqlLib.GetSql("job", "Task1"))
{
while (reader != null && reader.Read()) //Added null check as your GetSql could return null.
MessageBox.Show(reader[0].ToString());
}
I also stripped out reader.HasRows because it is unnessasary. If no results where returned the first call to reader.Read() will return false and the code inside the while loop will never execute.
You still need to close the connection when a exception occurs but you can just move the close from the finally in to the catch.
catch (Exception ex)
{
conn.Dispose(); //Disposing closes the connection.
return null;
}
you can try follow the next example http://msdn.microsoft.com/en-us/library/haa3afyz.aspx .
You shouldn't call to close method before to use your reader.
Jon Skeet and Scott Chamberlain are both correct. If you wish to keep with your way of structuring the code (as opposed to Jon Skeet's approach), you will need to modify your code so that the connection is closed should an error occur while executing the SqlCommand.
public static SqlDataReader GetSql(string businessUnit, string taskId)
{
const string connstring = "Connection string";
SqlConnection conn = null;
SqlCommand command = null;
SqlDataReader reader = null;
try
{
conn = new SqlConnection(connstring);
command = new SqlCommand();
command.Connection = conn;
command.CommandType = CommandType.Text;
command.CommandText = "SELECT * FROM Audits WHERE BusinessUnit = #BU AND TaskID = #TID";
command.Parameters.AddWithValue("#BU", businessUnit);
command.Parameters.AddWithValue("#TID", taskId);
conn.Open();
reader = command.ExecuteReader(CommandBehavior.CloseConnection);
conn = null;
return reader;
}
catch (Exception ex)
{
return null;
}
finally
{
if (conn != null) conn.Dispose();
if (command != null) command.Dispose();
}
}

in a "using" block is a SqlConnection closed on return or exception?

First question:
Say I have
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
Does the connection get closed? Because technically we never get to the last } as we return before it.
Second question:
This time I have:
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
}
catch (Exception) { /*Handle error*/ }
Now, say somewhere in the try we get an error and it gets caught. Does the connection still get closed? Because again, we skip the rest of the code in the try and go directly to the catch statement.
Am I thinking too linearly in how using works? ie Does Dispose() simply get called when we leave the using scope?
Yes
Yes.
Either way, when the using block is exited (either by successful completion or by error) it is closed.
Although I think it would be better to organize like this because it's a lot easier to see what is going to happen, even for the new maintenance programmer who will support it later:
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
try
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
catch (Exception)
{
/*Handle error*/
}
}
Yes to both questions. The using statement gets compiled into a try/finally block
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
is the same as
SqlConnection connection = null;
try
{
connection = new SqlConnection(connectionString);
}
finally
{
if(connection != null)
((IDisposable)connection).Dispose();
}
Edit: Fixing the cast to Disposable
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Here is my Template. Everything you need to select data from an SQL server. Connection is closed and disposed and errors in connection and execution are caught.
string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString;
string selectStatement = #"
SELECT TOP 1 Person
FROM CorporateOffice
WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%'
ORDER BY IntelligenceQuotient DESC
";
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
Console.WriteLine(dr["Person"].ToString());
}
}
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
}
* Revised: 2015-11-09 *
As suggested by NickG; If too many braces are annoying you, format like this...
using (SqlConnection conn = new SqlConnection(connString))
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
if (dr.HasRows)
while (dr.Read()) Console.WriteLine(dr["Person"].ToString());
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
Then again, if you work for EA or DayBreak games, you can just forgo any line-breaks as well because those are just for people who have to come back and look at your code later and who really cares? Am I right? I mean 1 line instead of 23 means I'm a better programmer, right?
using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); }
Phew... OK. I got that out of my system and am done amusing myself for a while. Carry on.
Dispose simply gets called when you leave the scope of using. The intention of "using" is to give developers a guaranteed way to make sure that resources get disposed.
From MSDN:
A using statement can be exited either when the end of the using statement is reached or if an exception is thrown and control leaves the statement block before the end of the statement.
Using generates a try / finally around the object being allocated and calls Dispose() for you.
It saves you the hassle of manually creating the try / finally block and calling Dispose()
In your first example, the C# compiler will actually translate the using statement to the following:
SqlConnection connection = new SqlConnection(connectionString));
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
Finally statements will always get called before a function returns and so the connection will be always closed/disposed.
So, in your second example the code will be compiled to the following:
try
{
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
}
catch (Exception)
{
}
The exception will be caught in the finally statement and the connection closed. The exception will not be seen by the outer catch clause.
I wrote two using statements inside a try/catch block and I could see the exception was being caught the same way if it's placed within the inner using statement just as ShaneLS example.
try
{
using (var con = new SqlConnection(#"Data Source=..."))
{
var cad = "INSERT INTO table VALUES (#r1,#r2,#r3)";
using (var insertCommand = new SqlCommand(cad, con))
{
insertCommand.Parameters.AddWithValue("#r1", atxt);
insertCommand.Parameters.AddWithValue("#r2", btxt);
insertCommand.Parameters.AddWithValue("#r3", ctxt);
con.Open();
insertCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
No matter where's the try/catch placed, the exception will be caught without issues.
Old thread but still relevant. I arrived here looking for a way out of having a using statement inside of a using statement. I am happy with this, notwithstanding any future insightful comments that change my mind. ;) Conversations here helped. Thanks. Simplified for readability -
public DataTable GetExchangeRates()
{
DataTable dt = new DataTable();
try
{
logger.LogInformation($"Log a message.");
string conStr = _config.GetConnectionString("conStr");
using (SqlCommand cmd = new SqlCommand("someProc", new SqlConnection(conStr)))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
dt.Load(cmd.ExecuteReader());
}
return dt;
}
catch (Exception ex)
{
logger.LogError(ex, ex.Message);
}
}

Categories