await/async Microsoft Practices Enterprise Library

2019-06-17 05:26发布

问题:

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?

回答1:

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);
}


回答2:

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.



回答3:

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);
}


回答4:

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