Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
This library is build against version 3.3.1.4000 of NHibernate so you will need to update to that version or later to use this library.
Version 2 of this library targets the new version (6) of the Enterprise Library code and as such requires .NET 4.5. If you have a .NET 4.0 application then feel free to use the latest version in the 1.0 range of this library.
To use the provider:
Update-Package FluentNHibernate
Install-Package NHibernate.SqlAzure
Install-Package NHibernate.SqlAzure.Standalone
(note: that will add 2 other dependencies as well)Set the Database
to use SqlAzureClientDriver
as the client driver (note: if you get Timeout exceptions then see the Advanced section below), e.g.:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString).Driver<SqlAzureClientDriver>())
To use the provider:
Update-Package NHibernate
Install-Package NHibernate.SqlAzure
Install-Package NHibernate.SqlAzure.Standalone
(note: that will add 2 other dependencies as well)connection.driver_class
property on the session factory configuration to NHibernate.SqlAzure.SqlAzureClientDriver, NHibernate.SqlAzure
(note: if you get Timeout exceptions then see the Advanced section below).We have NHibernate 4 supports via separate NuGet packages thanks to @rytmis:
Install-Package NHibernate4.SqlAzure
Install-Package NHibernate4.SqlAzure.Standalone
The Enterprise Library code doesn't seem to provide any rety logic when beginning transactions. This may be because it will rarely be a problem or you might not want to continue the transaction if there was a potential problem starting it. However, in order to get the unit tests for this library to pass, I needed the transaction to be resilient too so I created some classes that allow you to add retry logic when beginning a transaction. This may well be useful to others so we've included it as part of the library. See the next two sections to understand how to make use of this.
Set the TransactionStrategy
environment property to use the ReliableAdoNetWithDistributedTransactionFactory
class:
config.ExposeConfiguration(c => c.SetProperty(Environment.TransactionStrategy,
typeof(ReliableAdoNetWithDistributedTransactionFactory).AssemblyQualifiedName));
Set the transaction.factory_class
property on the session factory configuration to NHibernate.SqlAzure.ReliableAdoNetWithDistributedTransactionFactory, NHibernate.SqlAzure
.
It's possible for Timeout exceptions to be both a transient error caused by Azure and a legitimate timeout caused by unoptimised queries so we've included a transient error detection strategy that detects these timeout exceptions as a transient error and retries. To use it simply change your driver from SqlAzureClientDriver
to SqlAzureClientDriverWithTimeoutRetries
. There are a few things to note:
SqlAzureClientDriver
first and then add the one that detects timeouts as transient errors only after you experience timeout errors that you are sure are caused by SQL Azure and not your codeThere are two abstract base driver classes that you can extend to get more control over the retry policies and use to hook in logging of retries:
ReliableSql2008ClientDriver
: Takes care of wrapping the internals of NHibernate to use a ReliableSqlConnection
rather than a SqlConnection
. You simply need to override the CreateReliableConnection
method and instantiate your own ReliableSqlConnection
in any way you likeDefaultReliableSql2008ClientDriver<TTransientErrorDetectionStrategy>
:
RetryEventHandler
) or alternatively logging when a specific type of retry occurs (CommandRetryEventHandler
and ConnectionRetryEventHandler
)TTransientErrorDetectionStrategy
); there are two included in this library that you can use and / or extend (and of course you can always create a completely custom one by extending ITransientErrorDetectionStrategy
; for an example check out NHibernate.SqlAzure.Tests.Config.SqlExpressTransientErrorDetectionStrategy
in the test project of the source code):
NHibernate.SqlAzure.RetryStrategies.SqlAzureTransientErrorDetectionStrategy
: A clone of the error detection strategy that comes with the Transient Faut Handling library (except it's not sealed and the IsTransient
method is virtual so you can extend itNHibernate.SqlAzure.RetryStrategies.SqlAzureTransientErrorDetectionStrategyWithTimeouts
: The same as above with the addition of detecting timeout exceptions as a transient error; use this with caution as per aboveIf you want to contribute to this library then you need to:
NHibernateSqlAzureTests
and grant the user running the NUnit runner dbowner
access.
Database
ConnectionString in App.config
as well as the SqlServerServiceName
AppSetting if necessary.NHibernate.SqlAzure.Tests
project with your NUnit test runner of choice