├── .gitattributes
├── .gitignore
├── BREAKING_CHANGES.md
├── GitReleaseManager.yaml
├── GitVersionConfig.yaml
├── LICENSE
├── NHibernate.SqlAzure.Tests
├── App.Release.config
├── App.config
├── Config
│ ├── FluentRunner.cs
│ ├── LocalTestingReliableSql2008ClientDriver.cs
│ ├── NHibernateConfiguration.cs
│ ├── NHibernateTestBase.cs
│ └── SqlExpressTransientErrorDetectionStrategy.cs
├── ConnectionTests.cs
├── Entities
│ ├── User.cs
│ └── UserProperty.cs
├── Migrations
│ ├── 20120801141148_CreateUserTable.cs
│ └── 20120809201500_CreateUserPropertyTable.cs
├── NHibernate.SqlAzure.Tests.csproj
├── Properties
│ └── AssemblyInfo.cs
├── SqlClientDriverTests.cs
├── TransientErrorDetectionTests.cs
└── packages.config
├── NHibernate.SqlAzure.sln
├── NHibernate.SqlAzure
├── DefaultReliableSql2008ClientDriver.cs
├── NHibernate.SqlAzure.Standalone.nuspec
├── NHibernate.SqlAzure.csproj
├── NHibernate.SqlAzure.nuspec
├── Properties
│ └── AssemblyInfo.cs
├── ReliableAdoNetTransactionFactory.cs
├── ReliableAdoNetWithDistributedTransactionFactory.cs
├── ReliableAdoTransaction.cs
├── ReliableSql2008ClientDriver.cs
├── ReliableSqlClientBatchingBatcher.cs
├── ReliableSqlClientBatchingBatcherFactory.cs
├── ReliableSqlCommand.cs
├── ReliableSqlDbConnection.cs
├── RetryStrategies
│ ├── SqlAzureTransientErrorDetectionStrategy.cs
│ └── SqlAzureTransientErrorDetectionStrategyWithTimeouts.cs
├── SqlAzureClientDriver.cs
├── SqlAzureClientDriverWithTimeoutRetries.cs
└── packages.config
├── NHibernate4.SqlAzure.Tests
├── App.Release.config
├── App.config
├── NHibernate4.SqlAzure.Tests.csproj
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── NHibernate4.SqlAzure
├── NHibernate4.SqlAzure.Standalone.nuspec
├── NHibernate4.SqlAzure.csproj
├── NHibernate4.SqlAzure.nuspec
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── NHibernate5.SqlAzure.Tests
├── App.Release.config
├── App.config
├── App_Start
│ ├── NHibernateProfilerBootstrapper.cs
│ └── NHibernateProfilerBootstrapper.vb
├── NHibernate5.SqlAzure.Tests.csproj
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── NHibernate5.SqlAzure
├── NHibernate5.SqlAzure.Standalone.nuspec
├── NHibernate5.SqlAzure.csproj
├── NHibernate5.SqlAzure.nuspec
├── Properties
│ └── AssemblyInfo.cs
├── ReliableAdoNetWithDistributedTransactionFactory.cs
├── ReliableSql2008ClientDriver.cs
├── ReliableSqlClientBatchingBatcher.cs
├── ReliableSqlCommand.cs
└── packages.config
├── PreBuild.ps1
├── README.md
├── logo.png
└── packages
└── repositories.config
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | # Custom for Visual Studio
4 | *.cs diff=csharp
5 | *.sln merge=union
6 | *.csproj merge=union
7 | *.vbproj merge=union
8 | *.fsproj merge=union
9 | *.dbproj merge=union
10 |
11 | # Normalise endings to CRLF
12 | *.cs eol=crlf
13 | *.xml eol=crlf
14 | *.xaml eol=crlf
15 | *.xsl eol=crlf
16 | *.xsd eol=crlf
17 | *.cshtml eol=crlf
18 | *.css eol=crlf
19 | *.js eol=crlf
20 | *.txt eol=crlf
21 | *.config eol=crlf
22 | *.sql eol=crlf
23 | *.sln eol=crlf
24 | *.csproj eol=crlf
25 | *.vbproj eol=crlf
26 | *.fsproj eol=crlf
27 | *.dbproj eol=crlf
28 | *.nunit eol=crlf
29 | *.html eol=crlf
30 | *.md eol=crlf
31 | *.proj eol=crlf
32 | *.bat eol=crlf
33 | *.cmd eol=crlf
34 | *.nuspec eol=crlf
35 | *.targets eol=crlf
36 | *.conf eol=crlf
37 | *.manifest eol=crlf
38 | *.ps1 eol=crlf
39 | *.resx eol=crlf
40 | *.asax eol=crlf
41 | *.aspx eol=crlf
42 | *.ncrunchproject eol=crlf
43 | *.ncrunchsolution eol=crlf
44 | *.msbuild eol=crlf
45 | *.template eol=crlf
46 | *.settings eol=crlf
47 | *.java eol=crlf
48 | .gitattributes eol=crlf
49 | .classpath eol=crlf
50 | .project eol=crlf
51 |
52 | # Standard to msysgit
53 | *.doc diff=astextplain
54 | *.DOC diff=astextplain
55 | *.docx diff=astextplain
56 | *.DOCX diff=astextplain
57 | *.dot diff=astextplain
58 | *.DOT diff=astextplain
59 | *.pdf diff=astextplain
60 | *.PDF diff=astextplain
61 | *.rtf diff=astextplain
62 | *.RTF diff=astextplain
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | obj
2 | bin
3 | _ReSharper*
4 | *.csproj.user
5 | *.ReSharper.user
6 | *.ReSharper
7 | *.user
8 | *.suo
9 | *.cache
10 | ~$*
11 | *~
12 | *.log
13 | packages
14 | *.ncrunch*
15 | *.DotSettings
16 | /.vs/NHibernate.SqlAzure/v15/Server/sqlite3
17 |
--------------------------------------------------------------------------------
/BREAKING_CHANGES.md:
--------------------------------------------------------------------------------
1 | AzureWebFarm.OctopusDeploy Breaking Changes
2 | -------------------------------------------
3 |
4 | Version 2.0
5 | ===========
6 |
7 | 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](https://www.nuget.org/packages/NHibernate.SqlAzure/1.0.0.37).
8 |
9 | Version 2 also removes strong naming of the assembly - if you need strong naming then use version 1.
10 |
--------------------------------------------------------------------------------
/GitReleaseManager.yaml:
--------------------------------------------------------------------------------
1 | create:
2 | include-footer: true
3 | footer-heading: Where to get it
4 | footer-content: You can download this release from [nuget](https://www.nuget.org/packages?q=nhibernate.sqlazure)
5 | footer-includes-milestone: false
6 | milestone-replace-text: '{milestone}'
7 | export:
8 | include-created-date-in-title: false
9 | created-date-string-format: MMMM dd, yyyy
10 | perform-regex-removal: false
11 | regex-text: '### Where to get it(\r\n)*You can .*\)'
12 | multiline-regex: false
13 | issue-labels-include:
14 | - Bug
15 | - Feature
16 | - Improvement
17 | issue-labels-exclude:
18 | - Internal Refactoring
19 |
--------------------------------------------------------------------------------
/GitVersionConfig.yaml:
--------------------------------------------------------------------------------
1 | next-version: 3.0.0
2 | branches: {}
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2012 by Robert Moore
2 |
3 | The source code for NHibernate.SqlAzure is available under an MIT license as
4 | per below. If you are using the version of NHibernate.SqlAzure that is combined
5 | with the EnterpriseLibrary dlls then it is available under the EnterpriseLibrary
6 | license as per http://entlib.codeplex.com/license.
7 |
8 | -----
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in
18 | all copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 | THE SOFTWARE.
27 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/App.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Config/FluentRunner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Reflection;
4 | using FluentMigrator.Runner.Announcers;
5 | using FluentMigrator.Runner.Initialization;
6 |
7 | namespace NHibernate.SqlAzure.Tests.Config
8 | {
9 | public class FluentRunner
10 | {
11 | private readonly string _connectionString;
12 | private readonly Assembly _migrationAssembly;
13 | private readonly string _database;
14 | private long _version;
15 | private string _task;
16 |
17 | public FluentRunner(string connectionString, Assembly migrationAssembly, string database = "sqlserver2008")
18 | {
19 | _connectionString = connectionString;
20 | _migrationAssembly = migrationAssembly;
21 | _database = database;
22 | }
23 |
24 | public void MigrateTo(long version)
25 | {
26 | _version = version;
27 | _task = _version == 0 ? "rollback:all" : "rollback:toversion";
28 | Execute();
29 | }
30 |
31 | public void MigrateToLatest()
32 | {
33 | _task = "migrate:up";
34 | Execute();
35 | }
36 |
37 | private void Execute()
38 | {
39 | var announcer = new TextWriterAnnouncer(Console.Out) {ShowElapsedTime = true, ShowSql = true};
40 | var runnerContext = new RunnerContext(announcer)
41 | {
42 | Database = _database,
43 | Task = _task,
44 | Connection = _connectionString,
45 | Target = _migrationAssembly.CodeBase.Replace("file:///", ""),
46 | Version = _version
47 | };
48 |
49 | Trace.TraceInformation("#\n# Executing migration task {0}...\n#\n", _task);
50 | var task = new TaskExecutor(runnerContext);
51 | task.Execute();
52 | Trace.TraceInformation("\n#\n# Task {0} complete!\n#", _task);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Config/LocalTestingReliableSql2008ClientDriver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
3 |
4 | namespace NHibernate.SqlAzure.Tests.Config
5 | {
6 | public class LocalTestingReliableSql2008ClientDriver : DefaultReliableSql2008ClientDriver
7 | {
8 | protected override EventHandler CommandRetryEventHandler()
9 | {
10 | return LogRetry("Command");
11 | }
12 |
13 | protected override EventHandler ConnectionRetryEventHandler()
14 | {
15 | return LogRetry("Connection");
16 | }
17 |
18 | private static EventHandler LogRetry(string type)
19 | {
20 | return (sender, args) =>
21 | {
22 | var msg = String.Format("SQLAzureClientDriver {3} Retry - Count:{0}, Delay:{1}, Exception:{2}\r\n\r\n", args.CurrentRetryCount, args.Delay, args.LastException, type);
23 | Console.WriteLine(msg);
24 | };
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Config/NHibernateConfiguration.cs:
--------------------------------------------------------------------------------
1 | using FluentNHibernate.Automapping;
2 | using FluentNHibernate.Automapping.Alterations;
3 | using FluentNHibernate.Cfg;
4 | using FluentNHibernate.Cfg.Db;
5 | using HibernatingRhinos.Profiler.Appender.NHibernate;
6 | using NHibernate.Cfg;
7 | using NHibernate.Driver;
8 | using NHibernate.SqlAzure.Tests.Entities;
9 | using NHibernate.Tool.hbm2ddl;
10 |
11 | namespace NHibernate.SqlAzure.Tests.Config
12 | {
13 | public class NHibernateConfiguration where T : SqlClientDriver
14 | {
15 | private readonly string _connectionString;
16 | private readonly IPersistenceConfigurer _databaseConfig;
17 |
18 | public NHibernateConfiguration(string connectionString, IPersistenceConfigurer databaseConfig = null)
19 | {
20 | _connectionString = connectionString;
21 | _databaseConfig = databaseConfig ?? MsSqlConfiguration.MsSql2008.ConnectionString(_connectionString).Driver();
22 | }
23 |
24 | public ISessionFactory GetSessionFactory()
25 | {
26 | NHibernateProfiler.Initialize();
27 |
28 | var config = Fluently.Configure()
29 | .Database(_databaseConfig)
30 | .Mappings(m => m.AutoMappings
31 | .Add(AutoMap.AssemblyOf>()
32 | .Where(type => type.Namespace != null && type.Namespace.EndsWith("Entities"))
33 | .UseOverridesFromAssemblyOf>()
34 | )
35 | )
36 | // Ensure batching is used
37 | .ExposeConfiguration(c => c.SetProperty(Environment.BatchSize, "10"))
38 | // Turn off cache to make sure all calls actually go to the database
39 | .ExposeConfiguration(c => c.SetProperty(Environment.UseQueryCache, "false"))
40 | .ExposeConfiguration(c => c.SetProperty(Environment.UseSecondLevelCache, "false"));
41 |
42 | if (typeof(LocalTestingReliableSql2008ClientDriver).IsAssignableFrom(typeof(T)))
43 | config.ExposeConfiguration(c => c.SetProperty(Environment.TransactionStrategy,
44 | typeof(ReliableAdoNetWithDistributedTransactionFactory).AssemblyQualifiedName));
45 |
46 | var nhConfig = config.BuildConfiguration();
47 | SchemaMetadataUpdater.QuoteTableAndColumns(nhConfig);
48 | var validator = new SchemaValidator(nhConfig);
49 | validator.Validate();
50 |
51 | return config.BuildSessionFactory();
52 | }
53 | }
54 |
55 | public class UserPropertyOverride : IAutoMappingOverride
56 | {
57 | public void Override(AutoMapping mapping)
58 | {
59 | mapping.CompositeId().KeyProperty(u => u.Name).KeyReference(u => u.User, "UserId");
60 | }
61 | }
62 |
63 | public class UserOverride : IAutoMappingOverride
64 | {
65 | public void Override(AutoMapping mapping)
66 | {
67 | mapping.HasMany(u => u.Properties).KeyColumn("UserId").Cascade.All();
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Config/NHibernateTestBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 | using System.Data.SqlClient;
4 | using System.ServiceProcess;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using NHibernate.Driver;
8 | using NUnit.Framework;
9 |
10 | namespace NHibernate.SqlAzure.Tests.Config
11 | {
12 | public abstract class PooledNHibernateTestBase : NHibernateTestBase
13 | where T:SqlClientDriver
14 | {
15 | protected override string ConnectionString
16 | {
17 | get { return ConfigurationManager.ConnectionStrings["PooledDatabase"].ConnectionString; }
18 | }
19 | }
20 |
21 | public abstract class NonPooledNHibernateTestBase : NHibernateTestBase
22 | where T : SqlClientDriver
23 | {
24 | protected override string ConnectionString
25 | {
26 | get { return ConfigurationManager.ConnectionStrings["NonPooledDatabase"].ConnectionString; }
27 | }
28 | }
29 |
30 | public abstract class NHibernateTestBase where T: SqlClientDriver
31 | {
32 | private ISessionFactory _sessionFactory;
33 | protected FluentRunner Migrator;
34 |
35 | protected abstract string ConnectionString { get; }
36 |
37 | [TestFixtureSetUp]
38 | public void TestFixtureSetup()
39 | {
40 | CreateTestDatabase();
41 |
42 | Migrator = new FluentRunner(ConnectionString, typeof(NHibernateConfiguration<>).Assembly);
43 |
44 | if (_sessionFactory != null)
45 | return;
46 |
47 | Migrator.MigrateToLatest();
48 |
49 | var nHibernateConfig = new NHibernateConfiguration(ConnectionString);
50 | _sessionFactory = nHibernateConfig.GetSessionFactory();
51 | }
52 |
53 | private void CreateTestDatabase()
54 | {
55 | var connectionBuilder = new SqlConnectionStringBuilder(ConnectionString);
56 | var testDatabaseName = connectionBuilder.InitialCatalog;
57 | connectionBuilder.InitialCatalog = "master";
58 | using (var connection = new SqlConnection(connectionBuilder.ToString()))
59 | {
60 | connection.Open();
61 | using (var command = new System.Data.SqlClient.SqlCommand(
62 | string.Format("USE master IF NOT EXISTS(select * from sys.databases where name = '{0}') CREATE DATABASE {0}", testDatabaseName), connection
63 | ))
64 | {
65 | command.ExecuteNonQuery();
66 | }
67 | }
68 | }
69 |
70 | protected ISession CreateSession()
71 | {
72 | return _sessionFactory.OpenSession();
73 | }
74 |
75 | #region SQLExpress shutdown code
76 | private readonly ServiceController _serviceController = new ServiceController { MachineName = Environment.MachineName, ServiceName = ConfigurationManager.AppSettings["SqlServerServiceName"] };
77 |
78 | [TearDown]
79 | public void TearDown()
80 | {
81 | // Make sure that the service is running before stopping the test
82 | _serviceController.Refresh();
83 | if (_serviceController.Status == ServiceControllerStatus.PausePending)
84 | _serviceController.WaitForStatus(ServiceControllerStatus.Paused);
85 | if (_serviceController.Status == ServiceControllerStatus.ContinuePending)
86 | _serviceController.WaitForStatus(ServiceControllerStatus.Running);
87 |
88 | if (_serviceController.Status != ServiceControllerStatus.Running)
89 | {
90 | Console.WriteLine("SQLExpress service currently at {0} state; restarting...", _serviceController.Status);
91 | _serviceController.Continue();
92 | _serviceController.WaitForStatus(ServiceControllerStatus.Running);
93 | }
94 | }
95 |
96 | protected CancellableTask TemporarilyShutdownSqlServerExpress()
97 | {
98 | var tokenSource = new CancellationTokenSource();
99 | Task.Run(() =>
100 | {
101 | // tests run for about 5 seconds,
102 | // lets wait for 1 second and then pause for 3 seconds, this will assure a retry and a retry with backoff will happen
103 |
104 | Thread.Sleep(1000);
105 |
106 | _serviceController.Refresh();
107 | if (_serviceController.Status == ServiceControllerStatus.Running)
108 | _serviceController.Pause();
109 | _serviceController.WaitForStatus(ServiceControllerStatus.Paused);
110 |
111 | Console.WriteLine(DateTime.Now.ToString("s:fff") + " SQLServer paused");
112 | Thread.Sleep(3000);
113 |
114 | _serviceController.Refresh();
115 | _serviceController.Continue();
116 | _serviceController.WaitForStatus(ServiceControllerStatus.Running);
117 | Console.WriteLine(DateTime.Now.ToString("s:fff") + " SQLServer continued");
118 |
119 | }, tokenSource.Token);
120 |
121 | return new CancellableTask(tokenSource);
122 | }
123 |
124 | protected class CancellableTask : IDisposable
125 | {
126 | private readonly CancellationTokenSource _tokenSource;
127 |
128 | public CancellableTask(CancellationTokenSource tokenSource)
129 | {
130 | _tokenSource = tokenSource;
131 | }
132 |
133 | public void Dispose()
134 | {
135 | _tokenSource.Cancel();
136 | }
137 | }
138 | #endregion
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Config/SqlExpressTransientErrorDetectionStrategy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Linq;
4 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
5 |
6 | namespace NHibernate.SqlAzure.Tests.Config
7 | {
8 | public class SqlExpressTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy
9 | {
10 | public bool IsTransient(Exception ex)
11 | {
12 | if (ex is TransactionException)
13 | ex = ex.InnerException;
14 |
15 | // Is the error an error 17142 - The service is paused
16 | // Is the error an error 233 - Connection error when the process isn't responding
17 | var sqlException = ex as SqlException;
18 | return sqlException != null
19 | && sqlException.Errors.Cast().Any(error => error.Number == 17142 || error.Number == 233);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/ConnectionTests.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.SqlClient;
3 | using System.Threading;
4 | using NHibernate.Driver;
5 | using NHibernate.SqlAzure.Tests.Config;
6 | using NUnit.Framework;
7 |
8 | namespace NHibernate.SqlAzure.Tests
9 | {
10 | [TestFixture]
11 | class WhenConnectingLocalTestingSqlAzureClientDriverShould : ConnectionTests
12 | {
13 | [Test]
14 | public void Establish_connection_during_temporary_shutdown_of_sql_server()
15 | {
16 | TestConnectionEstablishment();
17 | }
18 | }
19 |
20 | [TestFixture]
21 | class WhenConnectingSql2008ClientDriverShould : ConnectionTests
22 | {
23 | [Test]
24 | public void Fail_to_establish_connection_during_temporary_shutdown_of_sql_server()
25 | {
26 | Assert.Throws(TestConnectionEstablishment, "No SqlException was thrown during temporary shutdown of SQL server, but one was expected.");
27 | }
28 | }
29 |
30 | abstract class ConnectionTests : NonPooledNHibernateTestBase
31 | where T : SqlClientDriver
32 | {
33 | protected void TestConnectionEstablishment()
34 | {
35 | using (TemporarilyShutdownSqlServerExpress())
36 | {
37 | for (var i = 0; i < 100; i++)
38 | {
39 | using (var session = CreateSession())
40 | {
41 | Assert.That(session.Connection.State == ConnectionState.Open);
42 | Thread.Sleep(50);
43 | }
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Entities/User.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace NHibernate.SqlAzure.Tests.Entities
4 | {
5 | public class User
6 | {
7 | public virtual int Id { get; set; }
8 | public virtual string Name { get; set; }
9 | public virtual IList Properties { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Entities/UserProperty.cs:
--------------------------------------------------------------------------------
1 | namespace NHibernate.SqlAzure.Tests.Entities
2 | {
3 | public class UserProperty
4 | {
5 | public virtual User User { get; set; }
6 | public virtual string Name { get; set; }
7 | public virtual string Value { get; set; }
8 |
9 | #region Equals
10 | public override bool Equals(object obj)
11 | {
12 | if (obj == null)
13 | return false;
14 | var a = obj as UserProperty;
15 | if (a == null)
16 | return false;
17 | if (User.Id == a.User.Id && Name == a.Name)
18 | return true;
19 | return false;
20 | }
21 | public override int GetHashCode()
22 | {
23 | return string.Format("{0}|{1}", User.Id, Name).GetHashCode();
24 | }
25 | #endregion
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Migrations/20120801141148_CreateUserTable.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 |
3 | namespace NHibernate.SqlAzure.Tests.Migrations
4 | {
5 | [Migration(20120801141148)]
6 | public class CreateUserTable : Migration
7 | {
8 | public override void Up()
9 | {
10 | Create.Table("User")
11 | .WithColumn("Id").AsInt32().PrimaryKey().Identity()
12 | .WithColumn("Name").AsString(255).NotNullable();
13 | }
14 |
15 | public override void Down()
16 | {
17 | Delete.Table("User");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Migrations/20120809201500_CreateUserPropertyTable.cs:
--------------------------------------------------------------------------------
1 | using FluentMigrator;
2 |
3 | namespace NHibernate.SqlAzure.Tests.Migrations
4 | {
5 | [Migration(20120809201500)]
6 | public class CreateUserPropertyTable : Migration
7 | {
8 | public override void Up()
9 | {
10 | Create.Table("UserProperty")
11 | .WithColumn("UserId").AsInt32().PrimaryKey()
12 | .WithColumn("Name").AsString(255).PrimaryKey()
13 | .WithColumn("Value").AsString(255);
14 | }
15 |
16 | public override void Down()
17 | {
18 | Delete.Table("User");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/NHibernate.SqlAzure.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}
9 | Library
10 | Properties
11 | NHibernate.SqlAzure.Tests
12 | NHibernate.SqlAzure.Tests
13 | v4.5
14 | 512
15 | ..\
16 |
17 |
18 |
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 | false
29 |
30 |
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 | false
38 |
39 |
40 |
41 | False
42 | ..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll
43 |
44 |
45 | False
46 | ..\packages\FluentMigrator.1.1.2.1\lib\40\FluentMigrator.dll
47 |
48 |
49 | False
50 | ..\packages\FluentMigrator.Runner.1.1.1.26\lib\NET40\FluentMigrator.Runner.dll
51 |
52 |
53 | False
54 | ..\packages\FluentNHibernate.1.4.0.0\lib\net35\FluentNHibernate.dll
55 |
56 |
57 | False
58 | ..\packages\NHibernateProfiler.1.0.0.951\lib\Net40\HibernatingRhinos.Profiler.Appender.v4.0.dll
59 |
60 |
61 | False
62 | ..\packages\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll
63 |
64 |
65 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
66 |
67 |
68 | ..\packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll
69 |
70 |
71 | True
72 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
73 |
74 |
75 | False
76 | ..\packages\NHibernate.3.3.3.4001\lib\Net35\NHibernate.dll
77 |
78 |
79 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | False
93 | ..\packages\WebActivator.1.4.4\lib\net40\WebActivator.dll
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | Designer
114 | true
115 |
116 |
117 | App.config
118 | True
119 |
120 |
121 |
122 |
123 |
124 | {C51908DF-FAEA-4EAA-8F75-096346537C33}
125 | NHibernate.SqlAzure
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
136 |
137 |
138 |
139 |
146 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NHibernate.SqlAzure.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NHibernate.SqlAzure.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("372cfa0d-2ae7-485c-952a-c0bd7d6cf86f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/SqlClientDriverTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using FizzWare.NBuilder;
6 | using NHibernate.Driver;
7 | using NHibernate.Exceptions;
8 | using NHibernate.SqlAzure.Tests.Config;
9 | using NHibernate.SqlAzure.Tests.Entities;
10 | using NUnit.Framework;
11 |
12 | namespace NHibernate.SqlAzure.Tests
13 | {
14 | // Run the tests against the standard Sql2008Client driver as well as the SqlAzureClientDriver
15 | // That way, we know if the test is broken because of the SqlAzureClientDriver or the test is wrong
16 | // Also, test the retry logic actually fires by using the LocalTestingReliableSql2008ClientDriver that provides
17 | // a reliable connection with a local error specific transient error detection strategy
18 | [TestFixture]
19 | class LocalTestingSqlAzureClientDriverShould : SqlClientDriverShould
20 | {
21 | [Test]
22 | public void Execute_non_batching_commands_during_temporary_shutdown_of_sql_server()
23 | {
24 | using (TemporarilyShutdownSqlServerExpress())
25 | {
26 | for (var i = 0; i < 100; i++)
27 | {
28 | Insert_and_select_entity();
29 | Thread.Sleep(50);
30 | }
31 | }
32 | }
33 |
34 | [Test]
35 | public void Execute_batching_commands_during_temporary_shutdown_of_sql_server()
36 | {
37 | using (TemporarilyShutdownSqlServerExpress())
38 | {
39 | for (var i = 0; i < 100; i++)
40 | {
41 | Insert_and_select_multiple_entities();
42 | Thread.Sleep(50);
43 | }
44 | }
45 | }
46 | }
47 |
48 | [TestFixture]
49 | class SqlAzureClientDriverShould : SqlClientDriverShould { }
50 |
51 | [TestFixture]
52 | class SqlAzureClientDriverWithTimeoutRetriesShould : SqlClientDriverShould { }
53 |
54 | [TestFixture]
55 | class Sql2008ClientDriverShould : SqlClientDriverShould
56 | {
57 | [Test]
58 | [ExpectedException(typeof(ExpectedErrorException))]
59 | public void Fail_to_execute_non_batching_commands_during_temporary_shutdown_of_sql_server()
60 | {
61 | try
62 | {
63 | using (TemporarilyShutdownSqlServerExpress())
64 | {
65 | for (var i = 0; i < 100; i++)
66 | {
67 | Insert_and_select_entity();
68 | Thread.Sleep(50);
69 | }
70 | }
71 | }
72 | catch (GenericADOException e)
73 | {
74 | Console.WriteLine(e);
75 | throw new ExpectedErrorException();
76 | }
77 | Assert.Fail("There was no exception when executing non batching commands during temporary shutdown of SQL server, but one was expected.");
78 | }
79 |
80 | [Test]
81 | [ExpectedException(typeof(ExpectedErrorException))]
82 | public void Fail_to_execute_batching_commands_during_temporary_shutdown_of_sql_server()
83 | {
84 | try
85 | {
86 | using (TemporarilyShutdownSqlServerExpress())
87 | {
88 | for (var i = 0; i < 100; i++)
89 | {
90 | Insert_and_select_multiple_entities();
91 | Thread.Sleep(50);
92 | }
93 | }
94 | }
95 | catch (GenericADOException e)
96 | {
97 | Console.WriteLine(e);
98 | throw new ExpectedErrorException();
99 | }
100 | catch (TransactionException e)
101 | {
102 | Console.WriteLine(e);
103 | throw new ExpectedErrorException();
104 | }
105 | }
106 | public class ExpectedErrorException : Exception { }
107 | }
108 |
109 | abstract class SqlClientDriverShould : PooledNHibernateTestBase where T : SqlClientDriver
110 | {
111 | [Test]
112 | public void Perform_empty_select()
113 | {
114 | using (var session = CreateSession())
115 | {
116 | var user = session.Get(-1);
117 |
118 | Assert.That(user, Is.Null);
119 | }
120 | }
121 |
122 | [Test]
123 | public void Insert_and_select_entity()
124 | {
125 | using (var session = CreateSession())
126 | using (var session2 = CreateSession())
127 | {
128 | var user = new User { Name = "Name" };
129 | session.Save(user);
130 |
131 | var dbUser = session2.Get(user.Id);
132 |
133 | Assert.That(dbUser.Name, Is.EqualTo(user.Name));
134 | }
135 | }
136 |
137 | [Test]
138 | public void Insert_and_select_multiple_entities()
139 | {
140 | using (var session = CreateSession())
141 | using (var session2 = CreateSession())
142 | {
143 | var users = Builder.CreateListOfSize(100)
144 | .All().With(u => u.Properties = new List
145 | {
146 | new UserProperty {Name = "Name", Value = "Value", User = u}
147 | })
148 | .Build().OrderBy(u => u.Name).ToList();
149 | using (var t = session.BeginTransaction())
150 | {
151 | users.ForEach(u => session.Save(u));
152 | t.Commit();
153 | }
154 |
155 | var dbUsers = session2.QueryOver()
156 | .WhereRestrictionOn(u => u.Id).IsIn(users.Select(u => u.Id).ToArray())
157 | .OrderBy(u => u.Name).Asc
158 | .List();
159 |
160 | Assert.That(dbUsers, Has.Count.EqualTo(users.Count));
161 | for (var i = 0; i < users.Count; i++)
162 | {
163 | Assert.That(dbUsers[i], Has.Property("Name").EqualTo(users[i].Name), "User " + i);
164 | Assert.That(dbUsers[i], Has.Property("Id").EqualTo(users[i].Id), "User " + i);
165 | var userProperties = dbUsers[i].Properties.ToList();
166 | Assert.That(userProperties, Is.Not.Null, "User " + i + " Properties");
167 | Assert.That(userProperties, Has.Count.EqualTo(1), "User " + i + " Properties");
168 | Assert.That(userProperties[0], Has.Property("Name").EqualTo("Name"), "User " + i + " property 0");
169 | Assert.That(userProperties[0], Has.Property("Value").EqualTo("Value"), "User " + i + " property 0");
170 | }
171 | }
172 | }
173 |
174 | [Test]
175 | public void Select_a_scalar()
176 | {
177 | using (var session = CreateSession())
178 | using (var session2 = CreateSession())
179 | {
180 | var users = Builder.CreateListOfSize(100).Build().ToList();
181 | using (var t = session.BeginTransaction())
182 | {
183 | users.ForEach(u => session.Save(u));
184 | t.Commit();
185 | }
186 |
187 | var count = session2.QueryOver()
188 | .WhereRestrictionOn(x => x.Id)
189 | .IsIn(users.Select(x => x.Id).ToArray())
190 | .RowCount();
191 |
192 | Assert.That(count, Is.EqualTo(100));
193 | }
194 | }
195 |
196 | [Test]
197 | public void Insert_and_update_an_entity()
198 | {
199 | using (var session = CreateSession())
200 | using (var session2 = CreateSession())
201 | {
202 | var user = new User { Name = "Name1" };
203 | session.Save(user);
204 | session.Flush();
205 | user.Name = "Name2";
206 | session.Flush();
207 |
208 | var userFromDb = session2.Get(user.Id);
209 |
210 | Assert.That(userFromDb.Name, Is.EqualTo("Name2"));
211 | }
212 | }
213 |
214 | [Test]
215 | public void Insert_and_update_multiple_entities()
216 | {
217 | using (var session = CreateSession())
218 | using (var session2 = CreateSession())
219 | {
220 | var users = Builder.CreateListOfSize(100).Build().ToList();
221 | using (var t = session.BeginTransaction())
222 | {
223 | users.ForEach(u => session.Save(u));
224 | t.Commit();
225 | }
226 | foreach (var u in users)
227 | {
228 | u.Name += "_2_";
229 | }
230 | session.Flush();
231 |
232 | var dbUsers = session2.QueryOver()
233 | .WhereRestrictionOn(u => u.Id).IsIn(users.Select(u => u.Id).ToArray())
234 | .OrderBy(u => u.Name).Asc
235 | .List();
236 |
237 | Assert.That(dbUsers, Has.Count.EqualTo(users.Count));
238 | foreach (var u in dbUsers)
239 | {
240 | Assert.That(u.Name, Is.StringEnding("_2_"));
241 | }
242 | }
243 | }
244 | }
245 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/TransientErrorDetectionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Reflection;
4 | using System.Runtime.Serialization;
5 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
6 | using NHibernate.Driver;
7 | using NHibernate.Exceptions;
8 | using NHibernate.SqlAzure.RetryStrategies;
9 | using NHibernate.SqlAzure.Tests.Config;
10 | using NUnit.Framework;
11 |
12 | namespace NHibernate.SqlAzure.Tests
13 | {
14 | [TestFixture]
15 | internal class SqlAzureTransientErrorDetectionStrategyWithTimeoutsShould :
16 | PooledNHibernateTestBase
17 | {
18 | [Test]
19 | public void Retry_when_timeout_occurs()
20 | {
21 | try
22 | {
23 | using (var session = CreateSession())
24 | {
25 | session.CreateSQLQuery(@"WAITFOR DELAY '00:02'").SetTimeout(1).ExecuteUpdate();
26 | }
27 | }
28 | catch (Exception e)
29 | {
30 | Assert.That(new SqlAzureTransientErrorDetectionStrategyWithTimeouts().IsTransient(e));
31 | return;
32 | }
33 | Assert.Fail("No timeout exception was thrown!");
34 | }
35 |
36 | [Test]
37 | public void Mark_unwrapped_timeout_exception_as_transient([Values(-2, 121)] int errorCode)
38 | {
39 | var e = SqlExceptionGenerator.GetSqlException(errorCode);
40 |
41 | Assert.That(new SqlAzureTransientErrorDetectionStrategyWithTimeouts().IsTransient(e));
42 | }
43 |
44 | [Test]
45 | public void Mark_wrapped_timeout_exception_as_transient([Values(-2, 121)] int errorCode)
46 | {
47 | var e = new GenericADOException("Wrapped exception", SqlExceptionGenerator.GetSqlException(errorCode));
48 |
49 | Assert.That(new SqlAzureTransientErrorDetectionStrategyWithTimeouts().IsTransient(e));
50 | }
51 |
52 | [Test]
53 | public void Mark_timeout_exception_as_transient()
54 | {
55 | var e = new TimeoutException();
56 |
57 | Assert.That(new SqlAzureTransientErrorDetectionStrategyWithTimeouts().IsTransient(e));
58 | }
59 | }
60 |
61 | [TestFixture(typeof(SqlAzureTransientErrorDetectionStrategy))]
62 | [TestFixture(typeof(SqlAzureTransientErrorDetectionStrategyWithTimeouts))]
63 | class TransientErrorDetectionStrategyShould : PooledNHibernateTestBase
64 | where TTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy, new()
65 | {
66 | [Test]
67 | public void Mark_unwrapped_exceptions_as_transient()
68 | {
69 | var e = SqlExceptionGenerator.GetSqlException(40197);
70 |
71 | Assert.That(new TTransientErrorDetectionStrategy().IsTransient(e));
72 | }
73 |
74 | [Test]
75 | public void Mark_nhibernate_adonet_wrapped_exceptions_as_transient()
76 | {
77 | var e = new GenericADOException("Wrapped exception", SqlExceptionGenerator.GetSqlException(40197));
78 |
79 | Assert.That(new TTransientErrorDetectionStrategy().IsTransient(e));
80 | }
81 |
82 | [Test]
83 | public void Mark_nhibernate_transaction_wrapped_exceptions_as_transient()
84 | {
85 | var e = new TransactionException("Wrapped exception", SqlExceptionGenerator.GetSqlException(40197));
86 |
87 | Assert.That(new TTransientErrorDetectionStrategy().IsTransient(e));
88 | }
89 |
90 | [Test]
91 | public void Mark_nhibernate_invalid_operation_exception_wrapped_exceptions_as_transient()
92 | {
93 | var e = new InvalidOperationException("Lazy load error", new GenericADOException("Wrapped exception", SqlExceptionGenerator.GetSqlException(40197)));
94 |
95 | Assert.That(new TTransientErrorDetectionStrategy().IsTransient(e));
96 | }
97 | }
98 |
99 | internal static class SqlExceptionGenerator
100 | {
101 | public static SqlException GetSqlException(int errorCode)
102 | {
103 | var collection = (SqlErrorCollection)Activator.CreateInstance(typeof(SqlErrorCollection), true);
104 | var error = (SqlError)Activator.CreateInstance(typeof(SqlError), BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { errorCode, (byte)2, (byte)3, "server name", "error message", "proc", 100 }, null);
105 |
106 | typeof(SqlErrorCollection)
107 | .GetMethod("Add", BindingFlags.NonPublic | BindingFlags.Instance)
108 | .Invoke(collection, new object[] { error });
109 |
110 | return typeof(SqlException)
111 | .GetMethod("CreateException", BindingFlags.NonPublic | BindingFlags.Static, null, new[] { typeof(SqlErrorCollection), typeof(string) }, null)
112 | .Invoke(null, new object[] { collection, "7.0.0" }) as SqlException;
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2010
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate.SqlAzure", "NHibernate.SqlAzure\NHibernate.SqlAzure.csproj", "{C51908DF-FAEA-4EAA-8F75-096346537C33}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{9C23CAA3-08A2-498A-AB98-F803AC42C49E}"
9 | ProjectSection(SolutionItems) = preProject
10 | BREAKING_CHANGES.md = BREAKING_CHANGES.md
11 | LICENSE = LICENSE
12 | logo.png = logo.png
13 | README.md = README.md
14 | EndProjectSection
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate.SqlAzure.Tests", "NHibernate.SqlAzure.Tests\NHibernate.SqlAzure.Tests.csproj", "{887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate4.SqlAzure", "NHibernate4.SqlAzure\NHibernate4.SqlAzure.csproj", "{BF649532-3E8A-4DC7-9F43-9AB25E475BF8}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate4.SqlAzure.Tests", "NHibernate4.SqlAzure.Tests\NHibernate4.SqlAzure.Tests.csproj", "{4864689E-5B40-4EA2-A797-63B2AEBFE5DC}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate5.SqlAzure", "NHibernate5.SqlAzure\NHibernate5.SqlAzure.csproj", "{895B6F59-B5BE-4796-847D-C3FF2C7EED66}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate5.SqlAzure.Tests", "NHibernate5.SqlAzure.Tests\NHibernate5.SqlAzure.Tests.csproj", "{BF71D707-D321-40DB-97CB-3A3A02F345D5}"
25 | EndProject
26 | Global
27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
28 | Debug|Any CPU = Debug|Any CPU
29 | Release|Any CPU = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {C51908DF-FAEA-4EAA-8F75-096346537C33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {C51908DF-FAEA-4EAA-8F75-096346537C33}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {C51908DF-FAEA-4EAA-8F75-096346537C33}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {C51908DF-FAEA-4EAA-8F75-096346537C33}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {887FD0A4-B8E0-4B3D-BF7E-4CC7090EB829}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {BF649532-3E8A-4DC7-9F43-9AB25E475BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {BF649532-3E8A-4DC7-9F43-9AB25E475BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {BF649532-3E8A-4DC7-9F43-9AB25E475BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {BF649532-3E8A-4DC7-9F43-9AB25E475BF8}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {4864689E-5B40-4EA2-A797-63B2AEBFE5DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {4864689E-5B40-4EA2-A797-63B2AEBFE5DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {4864689E-5B40-4EA2-A797-63B2AEBFE5DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {4864689E-5B40-4EA2-A797-63B2AEBFE5DC}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {895B6F59-B5BE-4796-847D-C3FF2C7EED66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {895B6F59-B5BE-4796-847D-C3FF2C7EED66}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {895B6F59-B5BE-4796-847D-C3FF2C7EED66}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {895B6F59-B5BE-4796-847D-C3FF2C7EED66}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {BF71D707-D321-40DB-97CB-3A3A02F345D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {BF71D707-D321-40DB-97CB-3A3A02F345D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {BF71D707-D321-40DB-97CB-3A3A02F345D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {BF71D707-D321-40DB-97CB-3A3A02F345D5}.Release|Any CPU.Build.0 = Release|Any CPU
56 | EndGlobalSection
57 | GlobalSection(SolutionProperties) = preSolution
58 | HideSolutionNode = FALSE
59 | EndGlobalSection
60 | GlobalSection(ExtensibilityGlobals) = postSolution
61 | SolutionGuid = {A2187D5F-03DE-4CF8-A458-16694FC9F9D6}
62 | EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45
63 | EndGlobalSection
64 | EndGlobal
65 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/DefaultReliableSql2008ClientDriver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
3 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// Default retry logic implementation for a that allows you to
9 | /// specify the transient error detection strategy.
10 | ///
11 | /// The transient error detection strategy you want to use
12 | public abstract class DefaultReliableSql2008ClientDriver : ReliableSql2008ClientDriver
13 | where TTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy, new()
14 | {
15 | protected override ReliableSqlConnection CreateReliableConnection()
16 | {
17 | const string incremental = "Incremental Retry Strategy";
18 | const string backoff = "Backoff Retry Strategy";
19 | var connectionRetry = new ExponentialBackoff(backoff, 10, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(10), false);
20 | var commandRetry = new Incremental(incremental, 10, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
21 |
22 | var connection = new ReliableSqlConnection(null,
23 | new RetryPolicy(connectionRetry),
24 | new RetryPolicy(commandRetry)
25 | );
26 | connection.ConnectionRetryPolicy.Retrying += ConnectionRetryEventHandler();
27 | connection.CommandRetryPolicy.Retrying += CommandRetryEventHandler();
28 | return connection;
29 | }
30 |
31 | ///
32 | /// An event handler delegate which will be called on connection retries.
33 | /// Only override this if you want to explicitly capture connection retries, otherwise override RetryEventHandler
34 | ///
35 | /// A custom method for handling the retry events
36 | protected virtual EventHandler ConnectionRetryEventHandler()
37 | {
38 | return RetryEventHandler();
39 | }
40 |
41 | ///
42 | /// An event handler delegate which will be called on command retries.
43 | /// Only override this if you want to explicitly capture command retries, otherwise override RetryEventHandler
44 | ///
45 | /// A custom method for handling the retry events
46 | protected virtual EventHandler CommandRetryEventHandler()
47 | {
48 | return RetryEventHandler();
49 | }
50 |
51 | ///
52 | /// An event handler delegate which will be called on connection and command retries.
53 | /// If you override ConnectionRetryEventHandler and CommandRetryEventHandler then this is redundant.
54 | ///
55 | /// A custom method for handling the retry events
56 | protected virtual EventHandler RetryEventHandler()
57 | {
58 | return null;
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/NHibernate.SqlAzure.Standalone.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate.SqlAzure.Standalone
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | Unlike NHibernate.SqlAzure, this library doesn't come with TransientFaultHandling IL-merged - instead it's a NuGet dependency.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/NHibernate.SqlAzure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {C51908DF-FAEA-4EAA-8F75-096346537C33}
9 | Library
10 | Properties
11 | NHibernate.SqlAzure
12 | NHibernate.SqlAzure
13 | v4.5
14 | 512
15 | ..\
16 |
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 | bin\Debug\NHibernate.SqlAzure.XML
27 | false
28 |
29 |
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 | bin\Release\NHibernate.SqlAzure.XML
37 | false
38 |
39 |
40 | false
41 |
42 |
43 |
44 | False
45 | ..\packages\Iesi.Collections.3.2.0.4000\lib\Net35\Iesi.Collections.dll
46 |
47 |
48 | False
49 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
50 |
51 |
52 | False
53 | ..\packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll
54 |
55 |
56 | False
57 | ..\packages\NHibernate.3.3.3.4001\lib\Net35\NHibernate.dll
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Component
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | Designer
91 |
92 |
93 | Designer
94 |
95 |
96 |
97 |
98 |
99 | mkdir "$(TargetDir)Combined"
100 | "$(ProjectDir)..\packages\ilmerge.2.14.1208\tools\ILMerge.exe" /v4 /target:library "$(TargetPath)" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll" /out:"$(TargetDir)Combined\NHibernate.SqlAzure.dll"
101 | copy "$(TargetDir)NHibernate.SqlAzure.XML" "$(TargetDir)Combined\NHibernate.SqlAzure.XML"
102 |
103 |
110 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/NHibernate.SqlAzure.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate.SqlAzure
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | This package has the Microsoft Transient Fault Handling library IL-merged into it; for a version that doesn't see the NHibernate.SqlAzure.Standalone package.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NHibernate.SqlAzure")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NHibernate.SqlAzure")]
13 | [assembly: AssemblyCopyright("Copyright © 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("cadcf8f5-3d8f-4949-937f-60d2acba588e")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableAdoNetTransactionFactory.cs:
--------------------------------------------------------------------------------
1 | using NHibernate.Engine;
2 | using NHibernate.Engine.Transaction;
3 | using NHibernate.Transaction;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// An NHibernate transaction factory that provides retry logic for transient errors when executing transactions.
9 | ///
10 | ///
11 | /// Requires the connection to be a
12 | ///
13 | public class ReliableAdoNetTransactionFactory : AdoNetTransactionFactory, ITransactionFactory
14 | {
15 | public new ITransaction CreateTransaction(ISessionImplementor session)
16 | {
17 | return new ReliableAdoTransaction(session);
18 | }
19 |
20 | ///
21 | /// Executes some work in isolation.
22 | ///
23 | /// The NHibernate session
24 | /// The work to execute
25 | /// Whether or not to wrap the work in a transaction
26 | public new void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork work, bool transacted)
27 | {
28 | var connection = (ReliableSqlDbConnection)session.Connection;
29 |
30 | ReliableAdoTransaction.ExecuteWithRetry(connection,
31 | () => base.ExecuteWorkInIsolation(session, work, transacted)
32 | );
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableAdoNetWithDistributedTransactionFactory.cs:
--------------------------------------------------------------------------------
1 | using NHibernate.Engine;
2 | using NHibernate.Engine.Transaction;
3 | using NHibernate.Transaction;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// An NHibernate transaction factory that provides retry logic for transient errors when executing transactions.
9 | /// It is aware of Distributed Transactions.
10 | ///
11 | ///
12 | /// Requires the connection to be a
13 | ///
14 | public class ReliableAdoNetWithDistributedTransactionFactory : AdoNetWithDistributedTransactionFactory, ITransactionFactory
15 | {
16 | public new ITransaction CreateTransaction(ISessionImplementor session)
17 | {
18 | return new ReliableAdoTransaction(session);
19 | }
20 |
21 | ///
22 | /// Executes some work in isolation.
23 | ///
24 | /// The NHibernate session
25 | /// The work to execute
26 | /// Whether or not to wrap the work in a transaction
27 | public new void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork work, bool transacted)
28 | {
29 | var connection = (ReliableSqlDbConnection) session.Connection;
30 |
31 | ReliableAdoTransaction.ExecuteWithRetry(connection,
32 | () => base.ExecuteWorkInIsolation(session, work, transacted)
33 | );
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableAdoTransaction.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using NHibernate.Engine;
3 | using NHibernate.Transaction;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// Provides a transaction implementation that includes transient fault-handling retry logic.
9 | ///
10 | public class ReliableAdoTransaction : AdoTransaction, ITransaction
11 | {
12 | private readonly ISessionImplementor _session;
13 |
14 | ///
15 | /// Constructs a .
16 | ///
17 | /// NHibernate session to use.
18 | public ReliableAdoTransaction(ISessionImplementor session) : base(session)
19 | {
20 | _session = session;
21 | }
22 |
23 | public new void Begin()
24 | {
25 | Begin(IsolationLevel.Unspecified);
26 | }
27 |
28 | public new void Begin(IsolationLevel isolationLevel)
29 | {
30 | ExecuteWithRetry(_session.Connection as ReliableSqlDbConnection, () => base.Begin(isolationLevel));
31 | }
32 |
33 | ///
34 | /// Executes the given action with the command retry policy on the given .
35 | ///
36 | /// The reliable connection
37 | /// The action to execute
38 | public static void ExecuteWithRetry(ReliableSqlDbConnection connection, System.Action action)
39 | {
40 | connection.ReliableConnection.CommandRetryPolicy.ExecuteAction(() =>
41 | {
42 | if (connection.State != ConnectionState.Open)
43 | connection.Open();
44 |
45 | action();
46 | }
47 | );
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableSql2008ClientDriver.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
3 | using NHibernate.AdoNet;
4 | using NHibernate.Driver;
5 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
6 |
7 | namespace NHibernate.SqlAzure
8 | {
9 | ///
10 | /// Abstract base class that enables the creation of an NHibernate client driver that extends the Sql 2008 driver,
11 | /// but adds in transient fault handling retry logic via .
12 | ///
13 | public abstract class ReliableSql2008ClientDriver : Sql2008ClientDriver, IEmbeddedBatcherFactoryProvider
14 | {
15 | ///
16 | /// Provides a instance to use for connections.
17 | ///
18 | /// A reliable connection
19 | protected abstract ReliableSqlConnection CreateReliableConnection();
20 |
21 | ///
22 | /// Creates an uninitialized object for the SqlClientDriver.
23 | ///
24 | ///
25 | /// An unitialized object.
26 | ///
27 | public override IDbConnection CreateConnection()
28 | {
29 | return new ReliableSqlDbConnection(CreateReliableConnection());
30 | }
31 |
32 | ///
33 | /// Creates an uninitialized object for the SqlClientDriver.
34 | ///
35 | ///
36 | /// An unitialized object.
37 | ///
38 | public override IDbCommand CreateCommand()
39 | {
40 | return new ReliableSqlCommand();
41 | }
42 |
43 | ///
44 | /// Returns the class to use for the Batcher Factory.
45 | ///
46 | public System.Type BatcherFactoryClass
47 | {
48 | get { return typeof(ReliableSqlClientBatchingBatcherFactory); }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableSqlClientBatchingBatcher.cs:
--------------------------------------------------------------------------------
1 | // Parts of this file were copied from NHibernate.AdoNet.SqlClientBatchingBatcherFactory, but modified to use ReliableSqlDbConnection
2 | // The #regions indicate the copied code
3 | using System;
4 | using System.Data;
5 | using System.Data.Common;
6 | using System.Reflection;
7 | using System.Text;
8 | using NHibernate.AdoNet;
9 | using NHibernate.AdoNet.Util;
10 | using NHibernate.Exceptions;
11 |
12 | namespace NHibernate.SqlAzure
13 | {
14 | ///
15 | /// Exposes functionality when a
16 | /// connection is being used.
17 | ///
18 | public class ReliableSqlClientBatchingBatcher : SqlClientBatchingBatcher
19 | {
20 | #region Impersonate private fields in base class
21 | private readonly ConnectionManager _connectionManager;
22 | private readonly FieldInfo _totalExpectedRowsAffectedField = typeof(SqlClientBatchingBatcher)
23 | .GetField("_totalExpectedRowsAffected", BindingFlags.NonPublic | BindingFlags.Instance);
24 | private readonly FieldInfo _currentBatchField = typeof (SqlClientBatchingBatcher)
25 | .GetField("_currentBatch", BindingFlags.NonPublic | BindingFlags.Instance);
26 | private readonly FieldInfo _currentBatchCommandsLogField = typeof(SqlClientBatchingBatcher)
27 | .GetField("_currentBatchCommandsLog", BindingFlags.NonPublic | BindingFlags.Instance);
28 | private readonly MethodInfo _createConfiguredBatchMethod = typeof (SqlClientBatchingBatcher)
29 | .GetMethod("CreateConfiguredBatch", BindingFlags.Instance | BindingFlags.NonPublic);
30 |
31 | // ReSharper disable InconsistentNaming
32 | private int _totalExpectedRowsAffected
33 | {
34 | get { return (int)_totalExpectedRowsAffectedField.GetValue(this); }
35 | set { _totalExpectedRowsAffectedField.SetValue(this, value); }
36 | }
37 | private SqlClientSqlCommandSet _currentBatch
38 | {
39 | get { return (SqlClientSqlCommandSet)_currentBatchField.GetValue(this); }
40 | set { _currentBatchField.SetValue(this, value); }
41 | }
42 | private StringBuilder _currentBatchCommandsLog
43 | {
44 | get { return (StringBuilder) _currentBatchCommandsLogField.GetValue(this); }
45 | set { _currentBatchCommandsLogField.SetValue(this, value); }
46 | }
47 | private int _batchSize
48 | {
49 | get { return BatchSize; }
50 | }
51 | // ReSharper restore InconsistentNaming
52 |
53 | private SqlClientSqlCommandSet CreateConfiguredBatch()
54 | {
55 | return (SqlClientSqlCommandSet)_createConfiguredBatchMethod.Invoke(this, null);
56 | }
57 |
58 | public ReliableSqlClientBatchingBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
59 | : base(connectionManager, interceptor)
60 | {
61 | _connectionManager = connectionManager;
62 | }
63 | #endregion
64 |
65 | public override void AddToBatch(IExpectation expectation)
66 | {
67 | #region NHibernate code
68 | _totalExpectedRowsAffected += expectation.ExpectedRowCount;
69 | IDbCommand batchUpdate = CurrentCommand;
70 | Driver.AdjustCommand(batchUpdate);
71 | string lineWithParameters = null;
72 | var sqlStatementLogger = Factory.Settings.SqlStatementLogger;
73 | if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled)
74 | {
75 | lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate);
76 | var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic);
77 | lineWithParameters = formatStyle.Formatter.Format(lineWithParameters);
78 | _currentBatchCommandsLog.Append("command ")
79 | .Append(_currentBatch.CountOfCommands)
80 | .Append(":")
81 | .AppendLine(lineWithParameters);
82 | }
83 | if (Log.IsDebugEnabled)
84 | {
85 | Log.Debug("Adding to batch:" + lineWithParameters);
86 | }
87 | #endregion
88 | _currentBatch.Append((System.Data.SqlClient.SqlCommand)(ReliableSqlCommand)batchUpdate);
89 | #region NHibernate code
90 | if (_currentBatch.CountOfCommands >= _batchSize)
91 | {
92 | ExecuteBatchWithTiming(batchUpdate);
93 | }
94 | #endregion
95 | }
96 |
97 | // Need this method call in this class rather than the base class to ensure Prepare is called... if only it was virtual :(
98 | protected void ExecuteBatch(IDbCommand ps)
99 | {
100 | #region NHibernate code
101 | Log.DebugFormat("Executing batch");
102 | CheckReaders();
103 | Prepare(_currentBatch.BatchCommand);
104 | if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
105 | {
106 | Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString());
107 | _currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
108 | }
109 |
110 | int rowsAffected;
111 | try
112 | {
113 | rowsAffected = _currentBatch.ExecuteNonQuery();
114 | }
115 | catch (DbException e)
116 | {
117 | throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command.");
118 | }
119 |
120 | Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowsAffected);
121 |
122 | _currentBatch.Dispose();
123 | _totalExpectedRowsAffected = 0;
124 | _currentBatch = CreateConfiguredBatch();
125 | #endregion
126 | }
127 |
128 | ///
129 | /// Prepares the for execution in the database.
130 | ///
131 | ///
132 | /// This takes care of hooking the up to an
133 | /// and if one exists. It will call Prepare if the Driver
134 | /// supports preparing commands.
135 | ///
136 | protected new void Prepare(IDbCommand cmd)
137 | {
138 | try
139 | {
140 | var sessionConnection = (ReliableSqlDbConnection)_connectionManager.GetConnection();
141 |
142 | #region NHibernate code
143 | if (cmd.Connection != null)
144 | {
145 | // make sure the commands connection is the same as the Sessions connection
146 | // these can be different when the session is disconnected and then reconnected
147 | if (cmd.Connection != sessionConnection)
148 | {
149 | cmd.Connection = (System.Data.SqlClient.SqlConnection) sessionConnection;
150 | }
151 | }
152 | else
153 | {
154 | cmd.Connection = (System.Data.SqlClient.SqlConnection) sessionConnection;
155 | }
156 |
157 | _connectionManager.Transaction.Enlist(cmd);
158 | Driver.PrepareCommand(cmd);
159 | #endregion
160 | }
161 | catch (InvalidOperationException ioe)
162 | {
163 | #region NHibernate code
164 | throw new ADOException("While preparing " + cmd.CommandText + " an error occurred", ioe);
165 | #endregion
166 | }
167 | }
168 |
169 | protected override void DoExecuteBatch(IDbCommand ps)
170 | {
171 | var connection = (ReliableSqlDbConnection)_connectionManager.GetConnection();
172 | ReliableAdoTransaction.ExecuteWithRetry(connection, () => ExecuteBatch(ps));
173 | }
174 | }
175 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableSqlClientBatchingBatcherFactory.cs:
--------------------------------------------------------------------------------
1 | // This file was copied from NHibernate.AdoNet.SqlClientBatchingBatcherFactory, but modified to use ReliableSqlClientBatchingBatcher
2 | using NHibernate.AdoNet;
3 | using NHibernate.Engine;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// An implementation that creates
9 | /// instances.
10 | ///
11 | public class ReliableSqlClientBatchingBatcherFactory : IBatcherFactory
12 | {
13 | ///
14 | /// Creates the batcher.
15 | ///
16 | /// The connection manager
17 | /// The interceptor
18 | /// The instance
19 | public virtual IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
20 | {
21 | return new ReliableSqlClientBatchingBatcher(connectionManager, interceptor);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableSqlCommand.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.SqlClient;
3 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
4 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
5 |
6 | namespace NHibernate.SqlAzure
7 | {
8 | ///
9 | /// An implementation that wraps a object such that any
10 | /// queries that are executed are executed via a .
11 | ///
12 | ///
13 | /// Note: For this to work it requires that the Connection property be set with a object.
14 | ///
15 | public class ReliableSqlCommand : IDbCommand
16 | {
17 | ///
18 | /// The underlying being proxied.
19 | ///
20 | public System.Data.SqlClient.SqlCommand Current { get; private set; }
21 |
22 | ///
23 | /// The that has been assigned to the command via the Connection property.
24 | ///
25 | public ReliableSqlConnection ReliableConnection { get; set; }
26 |
27 | ///
28 | /// Constructs a .
29 | ///
30 | public ReliableSqlCommand()
31 | {
32 | Current = new System.Data.SqlClient.SqlCommand();
33 | }
34 |
35 | ///
36 | /// Explicit type-casting between a and a .
37 | ///
38 | /// The being casted
39 | /// The underlying being proxied.
40 | public static explicit operator System.Data.SqlClient.SqlCommand(ReliableSqlCommand command)
41 | {
42 | return command.Current;
43 | }
44 |
45 | ///
46 | /// Returns the underlying and expects a when being set.
47 | ///
48 | public IDbConnection Connection
49 | {
50 | get { return Current.Connection; }
51 | set
52 | {
53 | ReliableConnection = ((ReliableSqlDbConnection)value).ReliableConnection;
54 | Current.Connection = ReliableConnection.Current;
55 | }
56 | }
57 |
58 | #region Wrapping code
59 | public void Dispose()
60 | {
61 | Current.Dispose();
62 | }
63 |
64 | public void Prepare()
65 | {
66 | Current.Prepare();
67 | }
68 |
69 | public void Cancel()
70 | {
71 | Current.Cancel();
72 | }
73 |
74 | public IDbDataParameter CreateParameter()
75 | {
76 | return Current.CreateParameter();
77 | }
78 |
79 | public int ExecuteNonQuery()
80 | {
81 | return ReliableConnection.ExecuteCommand(Current);
82 | }
83 |
84 | public IDataReader ExecuteReader()
85 | {
86 | return ReliableConnection.ExecuteCommand(Current);
87 | }
88 |
89 | public IDataReader ExecuteReader(CommandBehavior behavior)
90 | {
91 | return ReliableConnection.ExecuteCommand(Current, behavior);
92 | }
93 |
94 | public object ExecuteScalar()
95 | {
96 | return ReliableConnection.ExecuteCommand(Current);
97 | }
98 |
99 | public IDbTransaction Transaction
100 | {
101 | get { return Current.Transaction; }
102 | set { Current.Transaction = (SqlTransaction)value; }
103 | }
104 |
105 | public string CommandText
106 | {
107 | get { return Current.CommandText; }
108 | set { Current.CommandText = value; }
109 | }
110 |
111 | public int CommandTimeout
112 | {
113 | get { return Current.CommandTimeout; }
114 | set { Current.CommandTimeout = value; }
115 | }
116 |
117 | public CommandType CommandType
118 | {
119 | get { return Current.CommandType; }
120 | set { Current.CommandType = value; }
121 | }
122 |
123 | public IDataParameterCollection Parameters
124 | {
125 | get { return Current.Parameters; }
126 | }
127 |
128 | public UpdateRowSource UpdatedRowSource
129 | {
130 | get { return Current.UpdatedRowSource; }
131 | set { Current.UpdatedRowSource = value; }
132 | }
133 | #endregion
134 | }
135 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/ReliableSqlDbConnection.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.Common;
3 | using System.Data.SqlClient;
4 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
5 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
6 |
7 | namespace NHibernate.SqlAzure
8 | {
9 | ///
10 | /// Wrap in a class that extends
11 | /// so internal type casts within NHibernate don't fail.
12 | ///
13 | public class ReliableSqlDbConnection : DbConnection
14 | {
15 | bool disposed = false;
16 | ///
17 | /// The underlying .
18 | ///
19 | public ReliableSqlConnection ReliableConnection { get; set; }
20 |
21 | ///
22 | /// Constructs a to wrap around the given .
23 | ///
24 | /// The to wrap
25 | public ReliableSqlDbConnection(ReliableSqlConnection connection)
26 | {
27 | ReliableConnection = connection;
28 | }
29 |
30 | ///
31 | /// Explicit type-casting between and .
32 | ///
33 | /// The being casted
34 | /// The underlying
35 | public static explicit operator SqlConnection(ReliableSqlDbConnection connection)
36 | {
37 | return connection.ReliableConnection.Current;
38 | }
39 |
40 | protected override void Dispose(bool disposing) {
41 | if (disposed)
42 | return;
43 | if (disposing) {
44 | ReliableConnection.Dispose();
45 | }
46 | disposed = true;
47 | base.Dispose(disposing);
48 | }
49 |
50 | #region Wrapping code
51 | protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
52 | {
53 | return (DbTransaction) ReliableConnection.BeginTransaction(isolationLevel);
54 | }
55 |
56 | public override void Close()
57 | {
58 | ReliableConnection.Close();
59 | }
60 |
61 | public override DataTable GetSchema()
62 | {
63 | return ReliableConnection.ConnectionRetryPolicy.ExecuteAction (
64 | () => ReliableConnection.Current.GetSchema()
65 | );
66 | }
67 |
68 | public override DataTable GetSchema(string collectionName)
69 | {
70 | return ReliableConnection.ConnectionRetryPolicy.ExecuteAction (
71 | () => ReliableConnection.Current.GetSchema(collectionName)
72 | );
73 | }
74 |
75 | public override DataTable GetSchema(string collectionName, string[] restrictionValues)
76 | {
77 | return ReliableConnection.ConnectionRetryPolicy.ExecuteAction (
78 | () => ReliableConnection.Current.GetSchema(collectionName, restrictionValues)
79 | );
80 | }
81 |
82 | public override void ChangeDatabase(string databaseName)
83 | {
84 | ReliableConnection.ChangeDatabase(databaseName);
85 | }
86 |
87 | protected override DbCommand CreateDbCommand()
88 | {
89 | return ReliableConnection.CreateCommand();
90 | }
91 |
92 | public override void Open()
93 | {
94 | ReliableConnection.Open();
95 | }
96 |
97 | public override string ConnectionString { get { return ReliableConnection.ConnectionString; } set { ReliableConnection.ConnectionString = value; } }
98 | public override int ConnectionTimeout { get { return ReliableConnection.ConnectionTimeout; } }
99 | public override string Database { get { return ReliableConnection.Database; } }
100 | public override string DataSource { get { return ""; } }
101 | public override string ServerVersion { get { return ""; } }
102 | public override ConnectionState State { get { return ReliableConnection.State; } }
103 | #endregion
104 | }
105 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/RetryStrategies/SqlAzureTransientErrorDetectionStrategy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Linq;
4 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
5 |
6 |
7 | namespace NHibernate.SqlAzure.RetryStrategies
8 | {
9 | ///
10 | /// Transient error detection strategy for SQL Azure that is a copy of the Enterprise Library detection strategy.
11 | ///
12 | public class SqlAzureTransientErrorDetectionStrategy : ITransientErrorDetectionStrategy
13 | {
14 | // From Enterprise Library 6 changelog (see https://entlib.codeplex.com/wikipage?title=EntLib6ReleaseNotes):
15 | // Error code 40540 from SQL Database added as a transient error (see http://msdn.microsoft.com/en-us/library/ff394106.aspx#bkmk_throt_errors).
16 | // Added error codes 10928 and 10929 from SQL Database as transient errors (see http://blogs.msdn.com/b/psssql/archive/2012/10/31/worker-thread-governance-coming-to-azure-sql-database.aspx).
17 | // Added error codes 4060, 40197, 40501, 40613 from MSDN documentation (see https://azure.microsoft.com/en-us/documentation/articles/sql-database-develop-error-messages/)
18 |
19 | private readonly int[] _errorNumbers = new int[] { 40540, 10928, 10929, 4060, 40197, 40501, 40613 };
20 |
21 | private readonly SqlDatabaseTransientErrorDetectionStrategy _entLibStrategy = new SqlDatabaseTransientErrorDetectionStrategy();
22 |
23 | public virtual bool IsTransient(Exception ex)
24 | {
25 | return IsTransientAzureException(ex);
26 | }
27 |
28 | private bool IsTransientAzureException(Exception ex)
29 | {
30 | if (ex == null)
31 | return false;
32 |
33 | return _entLibStrategy.IsTransient(ex)
34 | || IsNewTransientError(ex)
35 | || IsTransientAzureException(ex.InnerException);
36 | }
37 |
38 | private bool IsNewTransientError(Exception ex)
39 | {
40 | SqlException sqlException;
41 | return (sqlException = ex as SqlException) != null
42 | && sqlException.Errors.Cast().Any(error => _errorNumbers.Contains(error.Number));
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/RetryStrategies/SqlAzureTransientErrorDetectionStrategyWithTimeouts.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.SqlClient;
3 | using System.Linq;
4 |
5 | namespace NHibernate.SqlAzure.RetryStrategies
6 | {
7 | ///
8 | /// Transient error detection strategy for SQL Azure that extends the Enterprise Library detection strategy and also detects timeout exceptions.
9 | ///
10 | public class SqlAzureTransientErrorDetectionStrategyWithTimeouts : SqlAzureTransientErrorDetectionStrategy
11 | {
12 | public override bool IsTransient(Exception ex)
13 | {
14 | return base.IsTransient(ex) || IsTransientTimeout(ex);
15 | }
16 |
17 | protected virtual bool IsTransientTimeout(Exception ex)
18 | {
19 | if (IsConnectionTimeout(ex))
20 | return true;
21 |
22 | return ex.InnerException != null && IsTransientTimeout(ex.InnerException);
23 | }
24 |
25 | protected virtual bool IsConnectionTimeout(Exception ex)
26 | {
27 | // Timeout exception: error code -2
28 | // http://social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/7a50985d-92c2-472f-9464-a6591efec4b3/
29 |
30 | // Timeout exception: error code 121
31 | // http://social.msdn.microsoft.com/Forums/nl-NL/ssdsgetstarted/thread/5e195f94-d4d2-4c2d-8a4e-7d66b4761510
32 |
33 | SqlException sqlException;
34 | return ex != null
35 | && (sqlException = ex as SqlException) != null
36 | && sqlException.Errors.Cast().Any(error => error.Number == -2 || error.Number == 121);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/SqlAzureClientDriver.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
2 |
3 | namespace NHibernate.SqlAzure
4 | {
5 | ///
6 | /// NHibernate client driver for SQL Azure that includes the Enterprise Library transient fault-handling.
7 | /// Note: It doesn't handle timeout errors, which can sometimes be transient. If you have timeout errors
8 | /// that aren't caused by unoptimised queries then use
9 | ///
10 | public class SqlAzureClientDriver : DefaultReliableSql2008ClientDriver {}
11 | }
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/SqlAzureClientDriverWithTimeoutRetries.cs:
--------------------------------------------------------------------------------
1 | using NHibernate.SqlAzure.RetryStrategies;
2 |
3 | namespace NHibernate.SqlAzure
4 | {
5 | ///
6 | /// NHibernate client driver for SQL Azure that includes the Enterprise Library transient fault-handling as well as timeout retries.
7 | /// Note: Timeout errors can be caused by unoptimised queries that you might be executing as well as being a transient exception.
8 | ///
9 | public class SqlAzureClientDriverWithTimeoutRetries : DefaultReliableSql2008ClientDriver {}
10 | }
11 |
--------------------------------------------------------------------------------
/NHibernate.SqlAzure/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure.Tests/App.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure.Tests/NHibernate4.SqlAzure.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4864689E-5B40-4EA2-A797-63B2AEBFE5DC}
8 | Library
9 | Properties
10 | NHibernate4.SqlAzure.Tests
11 | NHibernate4.SqlAzure.Tests
12 | v4.5
13 | 512
14 |
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 | ..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll
38 |
39 |
40 | ..\packages\FluentMigrator.1.1.2.1\lib\40\FluentMigrator.dll
41 |
42 |
43 | ..\packages\FluentMigrator.Runner.1.1.1.26\lib\NET40\FluentMigrator.Runner.dll
44 |
45 |
46 | False
47 | ..\packages\FluentNHibernate.2.0.1.0\lib\net40\FluentNHibernate.dll
48 |
49 |
50 | ..\packages\NHibernateProfiler.1.0.0.951\lib\Net40\HibernatingRhinos.Profiler.Appender.v4.0.dll
51 |
52 |
53 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
54 |
55 |
56 | ..\packages\NHibernate.4.1.0.4000\lib\net40\NHibernate.dll
57 | True
58 |
59 |
60 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Designer
79 | true
80 |
81 |
82 | App.config
83 | True
84 |
85 |
86 | Designer
87 |
88 |
89 |
90 |
91 | {bf649532-3e8a-4dc7-9f43-9ab25e475bf8}
92 | NHibernate4.SqlAzure
93 |
94 |
95 |
96 |
97 |
98 |
99 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
100 |
101 |
102 |
103 |
110 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NHibernate4.SqlAzure.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NHibernate4.SqlAzure.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("4864689e-5b40-4ea2-a797-63b2aebfe5dc")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure/NHibernate4.SqlAzure.Standalone.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate4.SqlAzure.Standalone
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | Unlike NHibernate.SqlAzure, this library doesn't come with TransientFaultHandling IL-merged - instead it's a NuGet dependency.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure/NHibernate4.SqlAzure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BF649532-3E8A-4DC7-9F43-9AB25E475BF8}
8 | Library
9 | Properties
10 | NHibernate.SqlAzure
11 | NHibernate.SqlAzure
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | bin\Debug\NHibernate.SqlAzure.XML
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | bin\Release\NHibernate.SqlAzure.XML
33 |
34 |
35 |
36 | ..\packages\Iesi.Collections.4.0.1.4000\lib\net40\Iesi.Collections.dll
37 |
38 |
39 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
40 |
41 |
42 | ..\packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll
43 |
44 |
45 | ..\packages\NHibernate.4.1.0.4000\lib\net40\NHibernate.dll
46 | True
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | Designer
63 |
64 |
65 | Designer
66 |
67 |
68 |
69 |
70 |
71 | mkdir "$(TargetDir)Combined"
72 | "$(ProjectDir)..\packages\ilmerge.2.14.1208\tools\ILMerge.exe" /v4 /target:library "$(TargetPath)" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll" /out:"$(TargetDir)Combined\NHibernate.SqlAzure.dll"
73 | copy "$(TargetDir)NHibernate.SqlAzure.XML" "$(TargetDir)Combined\NHibernate.SqlAzure.XML"
74 |
75 |
82 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure/NHibernate4.SqlAzure.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate4.SqlAzure
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | This package has the Microsoft Transient Fault Handling library IL-merged into it; for a version that doesn't see the NHibernate.SqlAzure.Standalone package.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NHibernate4.SqlAzure")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NHibernate4.SqlAzure")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("bf649532-3e8a-4dc7-9f43-9ab25e475bf8")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/NHibernate4.SqlAzure/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/App.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/App_Start/NHibernateProfilerBootstrapper.cs:
--------------------------------------------------------------------------------
1 | using HibernatingRhinos.Profiler.Appender.NHibernate;
2 |
3 | // If you're using .NET Core please remove this line and call NHibernateProfiler.Initialize(); on the very beginning of your application.
4 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NHibernate5.SqlAzure.Tests.App_Start.NHibernateProfilerBootstrapper), "PreStart")]
5 | namespace NHibernate5.SqlAzure.Tests.App_Start
6 | {
7 | public static class NHibernateProfilerBootstrapper
8 | {
9 | public static void PreStart()
10 | {
11 | // Initialize the profiler
12 | NHibernateProfiler.Initialize();
13 |
14 | // You can also use the profiler in an offline manner.
15 | // This will generate a file with a snapshot of all the NHibernate activity in the application,
16 | // which you can use for later analysis by loading the file into the profiler.
17 | // var filename = @"c:\profiler-log";
18 | // NHibernateProfiler.InitializeOfflineProfiling(filename);
19 |
20 | // You can use the following for production profiling.
21 | // NHibernateProfiler.InitializeForProduction(11234, "A strong password like: ze38r/b2ulve2HLQB8NK5AYig");
22 | }
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/App_Start/NHibernateProfilerBootstrapper.vb:
--------------------------------------------------------------------------------
1 | Imports HibernatingRhinos.Profiler.Appender.NHibernate
2 |
3 | ' If you're using .NET Core please remove this line and call NHibernateProfiler.Initialize() on the very beginning of your application.
4 |
5 | Namespace App_Start
6 | Public Class NHibernateProfilerBootstrapper
7 | Public Shared Sub PreStart()
8 | ' Initialize the profiler
9 | NHibernateProfiler.Initialize()
10 |
11 | ' You can also use the profiler in an offline manner.
12 | ' This will generate a file with a snapshot of all the NHibernate activity in the application,
13 | ' which you can use for later analysis by loading the file into the profiler.
14 | ' Dim FileName as String = @"c:\profiler-log";
15 | ' NHibernateProfiler.InitializeOfflineProfiling(FileName)
16 |
17 | ' You can use the following for production profiling.
18 | ' NHibernateProfiler.InitializeForProduction(11234, "A strong password like: ze38r/b2ulve2HLQB8NK5AYig");
19 | End Sub
20 | End Class
21 | End Namespace
22 |
23 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/NHibernate5.SqlAzure.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {BF71D707-D321-40DB-97CB-3A3A02F345D5}
7 | Library
8 | Properties
9 | NHibernate5.SqlAzure.Tests
10 | NHibernate5.SqlAzure.Tests
11 | v4.6.1
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 15.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 |
22 |
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE
28 | prompt
29 | 4
30 |
31 |
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 |
39 |
40 |
41 | ..\packages\Antlr3.Runtime.3.5.1\lib\net40-client\Antlr3.Runtime.dll
42 |
43 |
44 | ..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll
45 |
46 |
47 | ..\packages\FluentMigrator.1.1.2.1\lib\40\FluentMigrator.dll
48 |
49 |
50 | ..\packages\FluentMigrator.Runner.1.1.1.26\lib\NET40\FluentMigrator.Runner.dll
51 |
52 |
53 | ..\packages\FluentNHibernate.2.0.3.0\lib\net40\FluentNHibernate.dll
54 |
55 |
56 | ..\packages\NHibernateProfiler.5.0.5044\lib\net46\HibernatingRhinos.Profiler.Appender.dll
57 |
58 |
59 | ..\packages\Iesi.Collections.4.0.4\lib\net461\Iesi.Collections.dll
60 |
61 |
62 |
63 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
64 |
65 |
66 | ..\packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll
67 |
68 |
69 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
70 |
71 |
72 | ..\packages\NHibernate.5.2.3\lib\net461\NHibernate.dll
73 |
74 |
75 | ..\packages\NUnit.2.6.2\lib\nunit.framework.dll
76 |
77 |
78 | ..\packages\Remotion.Linq.2.2.0\lib\net45\Remotion.Linq.dll
79 |
80 |
81 | ..\packages\Remotion.Linq.EagerFetching.2.2.0\lib\net45\Remotion.Linq.EagerFetching.dll
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll
90 |
91 |
92 |
93 |
94 |
95 | ..\packages\WebActivator.1.4.4\lib\net40\WebActivator.dll
96 |
97 |
98 | ..\packages\WebActivatorEx.2.0.5\lib\net40\WebActivatorEx.dll
99 |
100 |
101 |
102 |
103 | FluentRunner.cs
104 |
105 |
106 | LocalTestingReliableSql2008ClientDriver.cs
107 |
108 |
109 | NHibernateConfiguration.cs
110 |
111 |
112 | NHibernateTestBase.cs
113 |
114 |
115 | SqlExpressTransientErrorDetectionStrategy.cs
116 |
117 |
118 | ConnectionTests.cs
119 |
120 |
121 | User.cs
122 |
123 |
124 | UserProperty.cs
125 |
126 |
127 | 20120801141148_CreateUserTable.cs
128 |
129 |
130 | 20120809201500_CreateUserPropertyTable.cs
131 |
132 |
133 | SqlClientDriverTests.cs
134 |
135 |
136 | TransientErrorDetectionTests.cs
137 |
138 |
139 |
140 |
141 |
142 |
143 | Designer
144 | true
145 |
146 |
147 | App.config
148 | True
149 |
150 |
151 | Designer
152 |
153 |
154 |
155 |
156 | {895b6f59-b5be-4796-847d-c3ff2c7eed66}
157 | NHibernate5.SqlAzure
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("NHibernate5.SqlAzure.Tests")]
6 | [assembly: AssemblyDescription("")]
7 | [assembly: AssemblyConfiguration("")]
8 | [assembly: AssemblyCompany("")]
9 | [assembly: AssemblyProduct("NHibernate5.SqlAzure.Tests")]
10 | [assembly: AssemblyCopyright("Copyright © 2018")]
11 | [assembly: AssemblyTrademark("")]
12 | [assembly: AssemblyCulture("")]
13 |
14 | [assembly: ComVisible(false)]
15 |
16 | [assembly: Guid("bf71d707-d321-40db-97cb-3a3a02f345d5")]
17 |
18 | // [assembly: AssemblyVersion("1.0.*")]
19 | [assembly: AssemblyVersion("1.0.0.0")]
20 | [assembly: AssemblyFileVersion("1.0.0.0")]
21 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/NHibernate5.SqlAzure.Standalone.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate5.SqlAzure.Standalone
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | Unlike NHibernate.SqlAzure, this library doesn't come with TransientFaultHandling IL-merged - instead it's a NuGet dependency.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/NHibernate5.SqlAzure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {895B6F59-B5BE-4796-847D-C3FF2C7EED66}
8 | Library
9 | Properties
10 | NHibernate.SqlAzure
11 | NHibernate.SqlAzure
12 | v4.6.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | bin\Debug\NHibernate.SqlAzure.xml
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | bin\Release\NHibernate.SqlAzure.xml
33 |
34 |
35 |
36 | ..\packages\Antlr3.Runtime.3.5.1\lib\net40-client\Antlr3.Runtime.dll
37 |
38 |
39 | ..\packages\Iesi.Collections.4.0.4\lib\net461\Iesi.Collections.dll
40 |
41 |
42 | ..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll
43 |
44 |
45 | ..\packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll
46 |
47 |
48 | ..\packages\NHibernate.5.2.3\lib\net461\NHibernate.dll
49 |
50 |
51 | ..\packages\Remotion.Linq.2.2.0\lib\net45\Remotion.Linq.dll
52 |
53 |
54 | ..\packages\Remotion.Linq.EagerFetching.2.2.0\lib\net45\Remotion.Linq.EagerFetching.dll
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | DefaultReliableSql2008ClientDriver.cs
71 |
72 |
73 | ReliableAdoNetTransactionFactory.cs
74 |
75 |
76 | ReliableAdoTransaction.cs
77 |
78 |
79 | ReliableSqlClientBatchingBatcherFactory.cs
80 |
81 |
82 | ReliableSqlDbConnection.cs
83 | Component
84 |
85 |
86 | SqlAzureTransientErrorDetectionStrategy.cs
87 |
88 |
89 | SqlAzureTransientErrorDetectionStrategyWithTimeouts.cs
90 |
91 |
92 | SqlAzureClientDriver.cs
93 |
94 |
95 | SqlAzureClientDriverWithTimeoutRetries.cs
96 |
97 |
98 |
99 |
100 |
101 |
102 | Component
103 |
104 |
105 |
106 |
107 | Designer
108 |
109 |
110 | Designer
111 |
112 |
113 |
114 |
115 |
116 | mkdir "$(TargetDir)Combined"
117 | "$(ProjectDir)..\packages\ilmerge.2.14.1208\tools\ILMerge.exe" /log:log.txt /v4 /target:library "$(TargetPath)" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll" "$(TargetDir)Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data.dll" /out:"$(TargetDir)Combined\NHibernate.SqlAzure.dll"
118 | copy "$(TargetDir)NHibernate.SqlAzure.XML" "$(TargetDir)Combined\NHibernate.SqlAzure.XML"
119 |
120 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/NHibernate5.SqlAzure.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NHibernate5.SqlAzure
6 |
7 |
8 | 2.0.0
9 |
10 |
11 | Robert Moore, Matthew Davies
12 |
13 |
14 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
15 | This package has the Microsoft Transient Fault Handling library IL-merged into it; for a version that doesn't see the NHibernate.SqlAzure.Standalone package.
16 |
17 |
18 | Please see https://github.com/MRCollective/NHibernate.SqlAzure/releases for release notes and https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/BREAKING_CHANGES.md for any breaking changes.
19 |
20 |
21 | https://github.com/MRCollective/NHibernate.SqlAzure
22 |
23 |
24 | https://github.com/MRCollective/NHibernate.SqlAzure/blob/master/LICENSE
25 |
26 |
27 | https://raw.github.com/MRCollective/NHibernate.SqlAzure/master/logo.png
28 |
29 |
30 | nhibernate, azure, sql, sql azure, transient
31 |
32 |
33 | en-US
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NHibernate5.SqlAzure")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NHibernate5.SqlAzure")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("895b6f59-b5be-4796-847d-c3ff2c7eed66")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/ReliableAdoNetWithDistributedTransactionFactory.cs:
--------------------------------------------------------------------------------
1 | using NHibernate.Engine;
2 | using NHibernate.Engine.Transaction;
3 | using NHibernate.Transaction;
4 |
5 | namespace NHibernate.SqlAzure
6 | {
7 | ///
8 | /// An NHibernate transaction factory that provides retry logic for transient errors when executing transactions.
9 | /// It is aware of Distributed Transactions.
10 | ///
11 | ///
12 | /// Requires the connection to be a
13 | ///
14 | public class ReliableAdoNetWithDistributedTransactionFactory : AdoNetWithSystemTransactionFactory, ITransactionFactory
15 | {
16 | public new ITransaction CreateTransaction(ISessionImplementor session)
17 | {
18 | return new ReliableAdoTransaction(session);
19 | }
20 |
21 | ///
22 | /// Executes some work in isolation.
23 | ///
24 | /// The NHibernate session
25 | /// The work to execute
26 | /// Whether or not to wrap the work in a transaction
27 | public new void ExecuteWorkInIsolation(ISessionImplementor session, IIsolatedWork work, bool transacted)
28 | {
29 | var connection = (ReliableSqlDbConnection) session.Connection;
30 |
31 | ReliableAdoTransaction.ExecuteWithRetry(connection,
32 | () => base.ExecuteWorkInIsolation(session, work, transacted)
33 | );
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/ReliableSql2008ClientDriver.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
3 | using NHibernate.AdoNet;
4 | using NHibernate.Driver;
5 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
6 |
7 | namespace NHibernate.SqlAzure
8 | {
9 | using System.Data.Common;
10 |
11 | ///
12 | /// Abstract base class that enables the creation of an NHibernate client driver that extends the Sql 2008 driver,
13 | /// but adds in transient fault handling retry logic via .
14 | ///
15 | public abstract class ReliableSql2008ClientDriver : Sql2008ClientDriver, IEmbeddedBatcherFactoryProvider
16 | {
17 | ///
18 | /// Provides a instance to use for connections.
19 | ///
20 | /// A reliable connection
21 | protected abstract ReliableSqlConnection CreateReliableConnection();
22 |
23 | ///
24 | /// Creates an uninitialized object for the SqlClientDriver.
25 | ///
26 | ///
27 | /// An unitialized object.
28 | ///
29 | public override DbConnection CreateConnection()
30 | {
31 | return new ReliableSqlDbConnection(CreateReliableConnection());
32 | }
33 |
34 | ///
35 | /// Creates an uninitialized object for the SqlClientDriver.
36 | ///
37 | ///
38 | /// An unitialized object.
39 | ///
40 | public override DbCommand CreateCommand()
41 | {
42 | return new ReliableSqlCommand();
43 | }
44 |
45 | ///
46 | /// Returns the class to use for the Batcher Factory.
47 | ///
48 | public System.Type BatcherFactoryClass
49 | {
50 | get { return typeof(ReliableSqlClientBatchingBatcherFactory); }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/ReliableSqlClientBatchingBatcher.cs:
--------------------------------------------------------------------------------
1 | // Parts of this file were copied from NHibernate.AdoNet.SqlClientBatchingBatcherFactory, but modified to use ReliableSqlDbConnection
2 | // The #regions indicate the copied code
3 | using System;
4 | using System.Data;
5 | using System.Data.Common;
6 | using System.Reflection;
7 | using System.Text;
8 | using NHibernate.AdoNet;
9 | using NHibernate.AdoNet.Util;
10 | using NHibernate.Exceptions;
11 |
12 | namespace NHibernate.SqlAzure
13 | {
14 | ///
15 | /// Exposes functionality when a
16 | /// connection is being used.
17 | ///
18 | public class ReliableSqlClientBatchingBatcher : SqlClientBatchingBatcher
19 | {
20 | #region Impersonate private fields in base class
21 | private readonly ConnectionManager _connectionManager;
22 | private readonly FieldInfo _totalExpectedRowsAffectedField = typeof(SqlClientBatchingBatcher)
23 | .GetField("_totalExpectedRowsAffected", BindingFlags.NonPublic | BindingFlags.Instance);
24 | private readonly FieldInfo _currentBatchField = typeof (SqlClientBatchingBatcher)
25 | .GetField("_currentBatch", BindingFlags.NonPublic | BindingFlags.Instance);
26 | private readonly FieldInfo _currentBatchCommandsLogField = typeof(SqlClientBatchingBatcher)
27 | .GetField("_currentBatchCommandsLog", BindingFlags.NonPublic | BindingFlags.Instance);
28 | private readonly MethodInfo _createConfiguredBatchMethod = typeof (SqlClientBatchingBatcher)
29 | .GetMethod("CreateConfiguredBatch", BindingFlags.Instance | BindingFlags.NonPublic);
30 |
31 | // ReSharper disable InconsistentNaming
32 | private int _totalExpectedRowsAffected
33 | {
34 | get { return (int)_totalExpectedRowsAffectedField.GetValue(this); }
35 | set { _totalExpectedRowsAffectedField.SetValue(this, value); }
36 | }
37 | private SqlClientSqlCommandSet _currentBatch
38 | {
39 | get { return (SqlClientSqlCommandSet)_currentBatchField.GetValue(this); }
40 | set { _currentBatchField.SetValue(this, value); }
41 | }
42 | private StringBuilder _currentBatchCommandsLog
43 | {
44 | get { return (StringBuilder) _currentBatchCommandsLogField.GetValue(this); }
45 | set { _currentBatchCommandsLogField.SetValue(this, value); }
46 | }
47 | private int _batchSize
48 | {
49 | get { return BatchSize; }
50 | }
51 | // ReSharper restore InconsistentNaming
52 |
53 | private SqlClientSqlCommandSet CreateConfiguredBatch()
54 | {
55 | return (SqlClientSqlCommandSet)_createConfiguredBatchMethod.Invoke(this, null);
56 | }
57 |
58 | public ReliableSqlClientBatchingBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
59 | : base(connectionManager, interceptor)
60 | {
61 | _connectionManager = connectionManager;
62 | }
63 | #endregion
64 |
65 | public override void AddToBatch(IExpectation expectation)
66 | {
67 | #region NHibernate code
68 | _totalExpectedRowsAffected += expectation.ExpectedRowCount;
69 | DbCommand batchUpdate = CurrentCommand;
70 | Driver.AdjustCommand(batchUpdate);
71 | string lineWithParameters = null;
72 | var sqlStatementLogger = Factory.Settings.SqlStatementLogger;
73 | if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled())
74 | {
75 | lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate);
76 | var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic);
77 | lineWithParameters = formatStyle.Formatter.Format(lineWithParameters);
78 | _currentBatchCommandsLog.Append("command ")
79 | .Append(_currentBatch.CountOfCommands)
80 | .Append(":")
81 | .AppendLine(lineWithParameters);
82 | }
83 | if (Log.IsDebugEnabled())
84 | {
85 | Log.Debug("Adding to batch:" + lineWithParameters);
86 | }
87 | #endregion
88 | _currentBatch.Append((System.Data.SqlClient.SqlCommand)(ReliableSqlCommand)batchUpdate);
89 | #region NHibernate code
90 | if (_currentBatch.CountOfCommands >= _batchSize)
91 | {
92 | ExecuteBatchWithTiming(batchUpdate);
93 | }
94 | #endregion
95 | }
96 |
97 | // Need this method call in this class rather than the base class to ensure Prepare is called... if only it was virtual :(
98 | protected void ExecuteBatch(IDbCommand ps)
99 | {
100 | #region NHibernate code
101 | Log.Debug("Executing batch");
102 | CheckReaders();
103 | Prepare(_currentBatch.BatchCommand);
104 | if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
105 | {
106 | Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString());
107 | _currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
108 | }
109 |
110 | int rowsAffected;
111 | try
112 | {
113 | rowsAffected = _currentBatch.ExecuteNonQuery();
114 | }
115 | catch (DbException e)
116 | {
117 | throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command.");
118 | }
119 |
120 | Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowsAffected);
121 |
122 | _currentBatch.Dispose();
123 | _totalExpectedRowsAffected = 0;
124 | _currentBatch = CreateConfiguredBatch();
125 | #endregion
126 | }
127 |
128 | ///
129 | /// Prepares the for execution in the database.
130 | ///
131 | ///
132 | /// This takes care of hooking the up to an
133 | /// and if one exists. It will call Prepare if the Driver
134 | /// supports preparing commands.
135 | ///
136 | protected new void Prepare(DbCommand cmd)
137 | {
138 | try
139 | {
140 | var sessionConnection = (ReliableSqlDbConnection)_connectionManager.GetConnection();
141 |
142 | #region NHibernate code
143 | if (cmd.Connection != null)
144 | {
145 | // make sure the commands connection is the same as the Sessions connection
146 | // these can be different when the session is disconnected and then reconnected
147 | if (cmd.Connection != sessionConnection)
148 | {
149 | cmd.Connection = (System.Data.SqlClient.SqlConnection) sessionConnection;
150 | }
151 | }
152 | else
153 | {
154 | cmd.Connection = (System.Data.SqlClient.SqlConnection) sessionConnection;
155 | }
156 |
157 | _connectionManager.Transaction.Enlist(cmd);
158 | Driver.PrepareCommand(cmd);
159 | #endregion
160 | }
161 | catch (InvalidOperationException ioe)
162 | {
163 | #region NHibernate code
164 | throw new ADOException("While preparing " + cmd.CommandText + " an error occurred", ioe);
165 | #endregion
166 | }
167 | }
168 |
169 | protected override void DoExecuteBatch(DbCommand ps)
170 | {
171 | var connection = (ReliableSqlDbConnection)_connectionManager.GetConnection();
172 | ReliableAdoTransaction.ExecuteWithRetry(connection, () => ExecuteBatch(ps));
173 | }
174 | }
175 | }
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/ReliableSqlCommand.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.SqlClient;
3 | using Microsoft.Practices.EnterpriseLibrary.WindowsAzure.TransientFaultHandling.SqlAzure;
4 | using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
5 |
6 | namespace NHibernate.SqlAzure
7 | {
8 | using System.Data.Common;
9 |
10 | ///
11 | /// An implementation that wraps a object such that any
12 | /// queries that are executed are executed via a .
13 | ///
14 | ///
15 | /// Note: For this to work it requires that the Connection property be set with a object.
16 | ///
17 | public class ReliableSqlCommand : DbCommand
18 | {
19 | ///
20 | /// The underlying being proxied.
21 | ///
22 | public System.Data.SqlClient.SqlCommand Current { get; private set; }
23 |
24 | ///
25 | /// The that has been assigned to the command via the Connection property.
26 | ///
27 | public ReliableSqlConnection ReliableConnection { get; set; }
28 |
29 | ///
30 | /// Constructs a .
31 | ///
32 | public ReliableSqlCommand()
33 | {
34 | Current = new System.Data.SqlClient.SqlCommand();
35 | }
36 |
37 | ///
38 | /// Explicit type-casting between a and a .
39 | ///
40 | /// The being casted
41 | /// The underlying being proxied.
42 | public static explicit operator System.Data.SqlClient.SqlCommand(ReliableSqlCommand command)
43 | {
44 | return command.Current;
45 | }
46 |
47 | ///
48 | /// Returns the underlying and expects a when being set.
49 | ///
50 | protected override DbConnection DbConnection
51 | {
52 | get { return Current.Connection; }
53 | set
54 | {
55 | ReliableConnection = ((ReliableSqlDbConnection)value).ReliableConnection;
56 | Current.Connection = ReliableConnection.Current;
57 | }
58 | }
59 |
60 |
61 | #region Wrapping code
62 |
63 |
64 | public override void Prepare()
65 | {
66 | Current.Prepare();
67 | }
68 |
69 | public override void Cancel()
70 | {
71 | Current.Cancel();
72 | }
73 |
74 | protected override DbParameter CreateDbParameter()
75 | {
76 | return Current.CreateParameter();
77 | }
78 |
79 | public override int ExecuteNonQuery()
80 | {
81 | return ReliableConnection.ExecuteCommand(Current);
82 | }
83 |
84 | public IDataReader ExecuteReader()
85 | {
86 | return ReliableConnection.ExecuteCommand(Current);
87 | }
88 |
89 | protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
90 | {
91 | return ReliableConnection.ExecuteCommand(Current, behavior);
92 | }
93 |
94 | public override object ExecuteScalar()
95 | {
96 | return ReliableConnection.ExecuteCommand(Current);
97 | }
98 |
99 | protected override DbTransaction DbTransaction
100 | {
101 | get { return Current.Transaction; }
102 | set { Current.Transaction = (SqlTransaction)value; }
103 | }
104 |
105 | public override bool DesignTimeVisible
106 | {
107 | get { return Current.DesignTimeVisible; }
108 | set { Current.DesignTimeVisible = value; }
109 | }
110 |
111 | public override string CommandText
112 | {
113 | get { return Current.CommandText; }
114 | set { Current.CommandText = value; }
115 | }
116 |
117 | public override int CommandTimeout
118 | {
119 | get { return Current.CommandTimeout; }
120 | set { Current.CommandTimeout = value; }
121 | }
122 |
123 | public override CommandType CommandType
124 | {
125 | get { return Current.CommandType; }
126 | set { Current.CommandType = value; }
127 | }
128 |
129 | protected override DbParameterCollection DbParameterCollection
130 | {
131 | get { return Current.Parameters; }
132 | }
133 |
134 | public override UpdateRowSource UpdatedRowSource
135 | {
136 | get { return Current.UpdatedRowSource; }
137 | set { Current.UpdatedRowSource = value; }
138 | }
139 | #endregion
140 | }
141 | }
--------------------------------------------------------------------------------
/NHibernate5.SqlAzure/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/PreBuild.ps1:
--------------------------------------------------------------------------------
1 |
2 | [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
3 | [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | Out-Null
4 |
5 | $serverName = $env:COMPUTERNAME
6 | $instanceName = 'SQL2019'
7 |
8 | $smo = 'Microsoft.SqlServer.Management.Smo.'
9 | $wmi = new-object ($smo + 'Wmi.ManagedComputer')
10 |
11 | # Enable TCP/IP
12 | $uri = "ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Tcp']"
13 | $Tcp = $wmi.GetSmoObject($uri)
14 | $Tcp.IsEnabled = $true
15 | $TCP.alter()
16 |
17 | # Enable named pipes
18 | $uri = "ManagedComputer[@Name='$serverName']/ ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Np']"
19 | $Np = $wmi.GetSmoObject($uri)
20 | $Np.IsEnabled = $true
21 | $Np.Alter()
22 |
23 | Set-Service SQLBrowser -StartupType Manual
24 | Start-Service SQLBrowser
25 | Start-Service "MSSQL`$$instanceName"
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | NHibernate Reliable SQL Azure Driver
2 | ====================================
3 |
4 | [](https://ci.appveyor.com/project/MRCollective/nhibernate-sqlazure)
5 | [](https://www.nuget.org/packages/NHibernate.SQLAzure)
6 | [](https://www.nuget.org/packages/NHibernate.SQLAzure)
7 |
8 | Provides an NHibernate driver that uses the Microsoft Transient Fault Handling library to allow for reliable SQL Azure connections.
9 |
10 | 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.
11 |
12 | 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](https://www.nuget.org/packages/NHibernate.SqlAzure/1.0.0.37).
13 |
14 | Using the provider when using Fluent NHibernate
15 | -----------------------------------------------
16 |
17 | To use the provider:
18 |
19 | 1. `Update-Package FluentNHibernate`
20 | 2. `Install-Package NHibernate.SqlAzure`
21 | * or if you want the version that isn't IL-merged with the Microsoft Transient Fault Handling library then `Install-Package NHibernate.SqlAzure.Standalone` (note: that will add 2 other dependencies as well)
22 | 3. Set the `Database` to use `SqlAzureClientDriver` as the client driver (note: if you get Timeout exceptions then see the Advanced section below), e.g.:
23 |
24 | Fluently.Configure()
25 | .Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString).Driver())
26 |
27 | Using the provider when using an XML configuration
28 | --------------------------------------------------
29 |
30 | To use the provider:
31 |
32 | 1. `Update-Package NHibernate`
33 | 2. `Install-Package NHibernate.SqlAzure`
34 | * or if you want the version that isn't IL-merged with the Microsoft Transient Fault Handling library then `Install-Package NHibernate.SqlAzure.Standalone` (note: that will add 2 other dependencies as well)
35 | 3. Set the `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).
36 |
37 | NHibernate 4 support
38 | --------------------
39 |
40 | We have NHibernate 4 supports via separate NuGet packages thanks to [@rytmis](https://github.com/rytmis):
41 |
42 | * `Install-Package NHibernate4.SqlAzure`
43 | * `Install-Package NHibernate4.SqlAzure.Standalone`
44 |
45 | Reliable transactions
46 | ---------------------
47 |
48 | 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.
49 |
50 | Using reliable transactions when using Fluent NHibernate
51 | --------------------------------------------------------
52 |
53 | Set the `TransactionStrategy` environment property to use the `ReliableAdoNetWithDistributedTransactionFactory` class:
54 |
55 | config.ExposeConfiguration(c => c.SetProperty(Environment.TransactionStrategy,
56 | typeof(ReliableAdoNetWithDistributedTransactionFactory).AssemblyQualifiedName));
57 |
58 | Using reliable transactions when using an XML configuration
59 | -----------------------------------------------------------
60 |
61 | Set the `transaction.factory_class` property on the session factory configuration to `NHibernate.SqlAzure.ReliableAdoNetWithDistributedTransactionFactory, NHibernate.SqlAzure`.
62 |
63 | Advanced Usage: Extending the provider, add logging for failed attempts or apply different retry strategies / transient error detection strategies
64 | ----------------------------------------------------------------------------------------------------------------------------------
65 |
66 | It's possible for Timeout exceptions to be both a [transient error caused by Azure and a legitimate timeout caused by unoptimised queries](http://social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/7a50985d-92c2-472f-9464-a6591efec4b3/) 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:
67 |
68 | * We recommend you try the `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 code
69 | * If the timeout happened in the first place it means that the user's request has already taken a long time so applying a retry policy to that query will make it take even longer (and if the retries also timeout then the page request might even time out (for a web application)).
70 | * If you want visibility of retries then see below for the instructions about how to log retries
71 |
72 | There 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:
73 |
74 | * `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 like
75 | * `DefaultReliableSql2008ClientDriver`:
76 | * Defines a connection and command retry policy (based on the example ones used in the [Transient Fault Handling documentation](http://msdn.microsoft.com/en-us/library/hh680900.aspx)
77 | * Includes overridable methods to return event handlers for logging when any retries occur (`RetryEventHandler`) or alternatively logging when a specific type of retry occurs (`CommandRetryEventHandler` and `ConnectionRetryEventHandler`)
78 | * Allows you to define what transient error detection strategy you want to use (`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):
79 | * `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 it
80 | * `NHibernate.SqlAzure.RetryStrategies.SqlAzureTransientErrorDetectionStrategyWithTimeouts`: The same as above with the addition of detecting timeout exceptions as a transient error; use this with caution as per above
81 |
82 | Running the tests
83 | -----------------
84 |
85 | If you want to contribute to this library then you need to:
86 |
87 | 1. Load the solution (allow the NuGet package restore to grab all the packages)
88 | 2. Compile the solution (.NET 4, AnyCPU)
89 | 3. Create a database on your local SQLExpress instance called `NHibernateSqlAzureTests` and grant the user running the NUnit runner `dbowner` access.
90 | * If you want to use a different database simply change the `Database` ConnectionString in `App.config` as well as the `SqlServerServiceName` AppSetting if necessary.
91 | 4. Run the `NHibernate.SqlAzure.Tests` project with your NUnit test runner of choice
92 | * The user running the tests must have Administrator access on the computer so that the Windows Service for the database can be shutdown and restarted
93 | * Note: Your database will be taken down and brought back up repeatedly when running the tests so only run them against a development database.
94 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MRCollective/NHibernate.SqlAzure/3e5615484df2f8abad5d803c91011a4c052d3563/logo.png
--------------------------------------------------------------------------------
/packages/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------