I have an older application that I wrote where I used Microsoft.Practices.EnterpriseLibrary.Data
to get data from the DB. I have recently upgraded to .NET 4.5 and wanted to advantage of await/async.
I do not see any methods ending in "Async" as per the naming standard, even in the most recent version of the package. Is it possible to use await/async with this ADO .NET library without manually making it asynchronous?
I'm using an older version of the EL that offers Begin* / End* methods, but not async versions. Some simple extension methods simplify life:
public static async Task<IDataReader> ExecuteReaderAsync(this SqlDatabase database, DbCommand command)
{
return await Task<IDataReader>.Factory.FromAsync(database.BeginExecuteReader, database.EndExecuteReader, command, null);
}
public static async Task<object> ExecuteScalarAsync(this SqlDatabase database, DbCommand command)
{
return await Task<object>.Factory.FromAsync(database.BeginExecuteScalar, database.EndExecuteScalar, command, null);
}
public static async Task<XmlReader> ExecuteXmlReaderAsync(this SqlDatabase database, DbCommand command)
{
return await Task<XmlReader>.Factory.FromAsync(database.BeginExecuteXmlReader, database.EndExecuteXmlReader, command, null);
}
public static async Task<int> ExecuteNonQueryAsync(this SqlDatabase database, DbCommand command)
{
return await Task<int>.Factory.FromAsync(database.BeginExecuteNonQuery, database.EndExecuteNonQuery, command, null);
}
I actually was able to find the Async methods. I was just looking in the wrong spots. Here's two common ways of accessing the DB asynchronously:
var db = DatabaseFactory.CreateDatabase(GlobalConstants.DBConnection);
using (var cmd = db.GetStoredProcCommand("SprocName", parameterA))
{
await cmd.ExecuteNonQueryAsync();
}
and when you want to get data:
var db = DatabaseFactory.CreateDatabase(GlobalConstants.DBConnection);
using (var cmd = db.GetStoredProcCommand("SprocName", parameterA, parameterB, parameterC))
{
using (var dr = await cmd.ExecuteReaderAsync())
{
while (await dr.ReadAsync())
{
return dr.GetInt32(0);
}
}
}
You can use GetFieldValueAsync<T>
instead of GetInt32
if you are using CommandBehavior.SequentialAccess
with large amounts of data. But, for most cases, you probably do not need to do this.
You'll probably find that it has methods like BeginXXX
and EndXXXX
, you can use those in conjunction with Task.Factory.FromAsync
. More information here.
Here is an example of using it to read a file using Task.Factory.FromAsync
in conjunction with filestream.BeginRead
and filestream.EndRead
private async Task<string> ReadFileAsync()
{
var fileStream = File.OpenRead("..\\..\\..\\test.txt");
var buffer = new byte[1024];
await Task<int>.Factory.FromAsync(fileStream.BeginRead, fileStream.EndRead, buffer, 0, buffer.Length, null);
return System.Text.Encoding.ASCII.GetString(buffer);
}
This package was written initially in .NET 4.0.
If you look at their source, they don't use async/await anywhere.
http://topaz.codeplex.com/SourceControl/latest#source/Source/TransientFaultHandling/AsyncExecution.cs