I have an SQL connection service that I'm trying to build. I essentially do this:
var data = await GetDataFromFlatFilesAsync(dir).ConfigureAwait(false);
using (var conn = new SqlConnection(MyConnectionString))
{
try
{
conn.Open();
var rw = new SqlReaderWriter(conn);
await DoStuffWithSqlAsync(rw, data).ConfigureAwait(false);
}
catch (Exception ex)
{
// Do exceptional stuff here
}
}
DoStuffWithSqlAsync
operates like this:
private async Task DoStuffWithSqlAsync(SqlReaderWriter rw, IEnumerable<Thing> data)
{
await Task.WhenAll(data.Select(rw.RunQueryAsync)).ConfigureAwait(false);
}
And RunQueryAsync
operates like this:
public async Task RunQueryAsync<T>(T content)
{
// _conn is assigned to in the constructor with conn
try
{
var dataQuery = _conn.CreateCommand();
dataQuery.CommandText = TranslateContentToQuery(content);
await dataQuery.ExecuteNonQueryAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
// Do exceptional stuff here
}
}
The problem I'm running into is that DoStuffWithSqlAsync
continuously fails with a System.InvalidOperationException
stating that conn is in a closed state. However, when I examine the stack trace, I find execution is still inside the using statement. I also know that conn
is not closed anywhere inside this operation as execution must necessarily return to the statement and any exception inside should be bubbled up to the enclosing try-catch and caught there. Additionally, the connection is pooled and MARS is enabled. So then, why is this being closed?
UPDATE: It was pointed out that I hadn't opened my connection. I have done so but the error persists except now _conn.State
is set to Open
.
UPDATE: I was having an issue wherein I used await conn.OpenAsync.ConfigureAwait(false);
which would not block execution. So, when I tried to connect to the database, I would get an exception stating that the connection state was closed but by that point it would have opened so on examination it would show Open. It was suggested that I make the calling method async void but as the application is console, not UI I don't think that will help. I have since reverted to using the synchronous method.
The connection is automatically closed at the end of the using block.
If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose . Close and Dispose are functionally equivalent. If the connection pooling value Pooling is set to true or yes , the underlying connection is returned back to the connection pool.
A SqlConnection object represents a unique session to a SQL Server data source. With a client/server database system, it is equivalent to a network connection to the server. SqlConnection is used together with SqlDataAdapter and SqlCommand to increase performance when connecting to a Microsoft SQL Server database.
The using statement handles the disposal and subsequent closing of my objects for me. Even if an exception is thrown, as soon as execution leaves the using block the DIspose method of the object is invoked under the covers. For objects like the SqlConnection, this also closes the connection too.
You just need to open the connection:
try
{
conn.Open() //<--add this
var rw = new SqlReaderWriter(conn);
await DoStuffWithSqlAsync(rw, data).ConfigureAwait(false);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With