A new version of Enterprise Library was recently released along with a new version of the Transient Fault Handling Application Block and It brings a couple changes when it come to querying SQL Database using ADO.NET.
The first apparent changes
- Namespace Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure has been replaced by Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling
- SqlAzureTransientErrorDetectionStrategy has been replaced by SqlDatabaseTransientErrorDetectionStrategy
- The NuGet package has been exploded into many individual packages linked to a primary package.
- Take a look at the Migration Guide & the project on CodePlex
Ok, so now that I got that out of the way, here are some examples using the new version of the Transient Fault Handling Application Block.
Execute an SqlCommand with Retries
This example is base off a previous post where I demonstrated how to insert a large amount of data Into Windows Azure SQL Database. This example is slightly different because it uses Enterprise Library 6.
1) Start by setting the default RetryManager
const int retryCount = 10;
var retryInterval = TimeSpan.FromSeconds(3);
var strategy = new FixedInterval(defaultRetryStrategyName, retryCount, retryInterval);
var strategies = new List<RetryStrategy> { strategy };
var manager = new RetryManager(strategies, defaultRetryStrategyName);
RetryManager.SetDefault(manager);
2) Create a DataTable that matches the Stored Procedure’s User Defined Type parameter
// add columns
// fill the DataTable with data
3) Execute the Stored Procedure with the DataTable
using (var con = new ReliableSqlConnection(connectionString))
{
using (var cmd = new SqlCommand("EXEC CustomStoredProcedure", con.Current))
{
var sqlParameter = new SqlParameter("table", SqlDbType.Structured)
{
Value = dataTable
};
cmd.Parameters.Add(sqlParameter);
cmd.ExecuteNonQueryWithRetry();
}
}
Execute an SqlDataReader with Retries
When you need to read results from a Stored Procedure, you might not absolutely need Entity Framework. One reason to use ADO.NET is speed. Entity Framework is built on top of ADO.NET and with each layer of abstraction we have extra latency. The DataReader remains the fastest way to read data from Windows Azure SQL Database.
1) Setup the default RetryManager
const int retryCount = 10;
var retryInterval = TimeSpan.FromSeconds(3);
var strategy = new FixedInterval(defaultRetryStrategyName, retryCount, retryInterval);
var strategies = new List<RetryStrategy> { strategy };
var manager = new RetryManager(strategies, defaultRetryStrategyName);
RetryManager.SetDefault(manager);
2) Create an SqlCommand that invokes your Stored Procedure, then to get a transient fault tolerant DataReader you will need to call the ExecuteReaderWithRetry, extension method provided by the Transient Fault Handling Application Block, found on the SqlCommand instance.
string username = string.Empty;
var connectionString = CloudConfigurationManager.GetSetting("DatabaseConnectionString");
using (var con = new ReliableSqlConnection(connectionString))
{
using (var cmd = new SqlCommand("EXEC GetUserStoredProcedure", con.Current))
{
var sqlParameter = new SqlParameter("id", SqlDbType.UniqueIdentifier)
{
Value = userId
};
cmd.Parameters.Add(sqlParameter);
using (var reader = cmd.ExecuteReaderWithRetry())
{
if (reader.Read())
username = reader.GetString(0);
}
}
}
Console.WriteLine("Found user {0}", username);
Fill a DataTable Using an SqlDataAdapter With Retries
DataTables a great at retrieving data without materializing it into objects. Entity Framework is great for working with normal amounts of data, but when you start playing with batching and large amounts of data you need DataTables.
1) Setup the default RetryManager
const int retryCount = 10;
var retryInterval = TimeSpan.FromSeconds(3);
var strategy = new FixedInterval(defaultRetryStrategyName, retryCount, retryInterval);
var strategies = new List<RetryStrategy> { strategy };
var manager = new RetryManager(strategies, defaultRetryStrategyName);
RetryManager.SetDefault(manager);
2) Create a RetryPolicy and an SqlCommand that invokes your Stored Procedure, then create an SqlDataAdapter and fill the Datatable.
var userId = new Guid("EDFEB4AE-02C2-4153-A331-E2CA95D43D1E");
var connectionString = CloudConfigurationManager.GetSetting("DatabaseConnectionString");
var retryPolicy = new RetryPolicy(new SqlDatabaseTransientErrorDetectionStrategy(), 10);
retryPolicy.ExecuteAction(() =>
{
using (var con = new ReliableSqlConnection(connectionString))
{
con.Open(retryPolicy);
using (var cmd = new SqlCommand("EXEC GetUserStoredProcedure", con.Current))
{
var sqlParameter = new SqlParameter("id", SqlDbType.UniqueIdentifier)
{
Value = userId
};
cmd.Parameters.Add(sqlParameter);
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dataTable);
}
}
}
});
In Summary
There are times when you need to use ADO.NET in order to optimize your interactions with Windows Azure SQL Database. Since transient faults are common, using the Transient Fault Handling Application Block is essential when it comes to interacting with it. These examples can serve as a good starting point in your efforts to build applications that work with large amounts of data stored in Windows Azure SQL Database.
Hey when i am trying to create an objext to that retryManager. it says u cant
LikeLike
Can you give me more details? What version of EF are you using?
LikeLike
Hey i found a solution to that. Thanks anyway and by the way i would like to ask you how can i inplement the same logic in my MVC application(which’s been already developed)
LikeLike
Hi,
What was your solution? If you give me some information about how you use EF in your solution I will try to give you some pointers
Best regards,
Alex
LikeLike