Skip to content

Instantly share code, notes, and snippets.

@andreazevedo
Forked from lukemcgregor/nhrollback
Created September 20, 2012 20:48
Show Gist options
  • Save andreazevedo/3758267 to your computer and use it in GitHub Desktop.
Save andreazevedo/3758267 to your computer and use it in GitHub Desktop.
Do NHibernate Transactions rollback with parent transaction scope?
using System;
using System.Data.SqlServerCe;
using System.IO;
using System.Reflection;
using Moq;
using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace Tests
{
public class SqlCeTestDatabase
{
private static ISessionFactory _sessionFactory;
private static Configuration _configuration;
private SqlCeConnection _connection;
private string _connectionString;
protected Mock<ISessionFactory> _mockSessionFactory;
public SqlCeTestDatabase(Assembly hbmlAssembly,string filePath = null)
{
filePath = filePath ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"db_test.sdf");
_connectionString = string.Format("Data Source={0}", filePath);
if (_configuration == null)
{
try
{
_configuration = GetConfigurationFromConnectionString(_connectionString,hbmlAssembly);
CreateDb(filePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
public SqlCeTestDatabase(string hbmlXml, string name, string filePath = null)
{
filePath = filePath ?? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"db_test.sdf");
_connectionString = string.Format("Data Source={0}", filePath);
if (_configuration == null)
{
try
{
_configuration = GetConfigurationFromConnectionString(_connectionString, hbmlXml,name);
CreateDb(filePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
private void CreateDb(string filePath)
{
// create the database
if (!File.Exists(filePath))
{
using (SqlCeEngine engine = new SqlCeEngine(_connectionString))
{
engine.CreateDatabase();
}
}
_sessionFactory = _configuration.BuildSessionFactory();
}
public Configuration GetConfigurationFromConnectionString(string connectionString, Assembly hbmlAssembly)
{
return new Configuration()
.SetProperty(NHibernate.Cfg.Environment.ReleaseConnections, "on_close")
.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.MsSqlCeDialect")
.SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider")
.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.SqlServerCeDriver")
.SetProperty(NHibernate.Cfg.Environment.ConnectionString, connectionString)
.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName)
.AddAssembly(hbmlAssembly);
}
public Configuration GetConfigurationFromConnectionString(string connectionString, string hbmlXml, string name)
{
return new Configuration()
.SetProperty(NHibernate.Cfg.Environment.ReleaseConnections, "on_close")
.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.MsSqlCeDialect")
.SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider")
.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.SqlServerCeDriver")
.SetProperty(NHibernate.Cfg.Environment.ConnectionString, connectionString)
.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName)
.AddXml(hbmlXml,name);
}
public virtual void SetUpNewDatabase()
{
_connection = new SqlCeConnection(_connectionString);
_connection.Open();
new SchemaExport(_configuration).Execute(true, true, false, _connection, System.Console.Out);
_mockSessionFactory = new Mock<ISessionFactory>();
_mockSessionFactory.Setup(x => x.OpenSession()).Returns(() => CreateSession());
_mockSessionFactory.Setup(x => x.OpenStatelessSession()).Returns(() => CreateStatelessSession());
}
public virtual void SetUpSessionFactory()
{
_mockSessionFactory = new Mock<ISessionFactory>();
_mockSessionFactory.Setup(x => x.OpenSession()).Returns(() => CreateSession());
_mockSessionFactory.Setup(x => x.OpenStatelessSession()).Returns(() => CreateStatelessSession());
}
public ISession CreateSession()
{
return _sessionFactory.OpenSession(_connection);
}
public IStatelessSession CreateStatelessSession()
{
return _sessionFactory.OpenStatelessSession(_connection);
}
public ISessionFactory GetSessionFactory()
{
return _mockSessionFactory.Object;
}
}
[TestClass]
public class TestRollbackScenarios
{
[TestMethod]
public void DoNHibernateTransactionsRollbackOnParentRollback() //Fails
{
SqlCeTestDatabase db = new SqlCeTestDatabase(@"<?xml version=""1.0"" encoding=""utf-8""?>
<hibernate-mapping xmlns=""urn:nhibernate-mapping-2.2"" assembly=""Tests"" namespace=""Tests"">
<class name=""Tests.TestEntity, Tests"" table=""TestEntities"" >
<id name=""Id"" column=""Id"" type=""Int32"" />
</class>
</hibernate-mapping>", "Test");
db.SetUpNewDatabase();
using (var tx = new TransactionScope(TransactionScopeOption.Required))
{
using (var session = db.CreateSession())
using(var nhTx = session.BeginTransaction())
{
session.Save(new TestEntity
{
});
nhTx.Commit();
}
//no complete so should rollback
}
using (var session = db.CreateSession())
{
Assert.AreEqual(0, session.CreateCriteria<TestEntity>().List<TestEntity>().Count());
}
}
[TestMethod]
public void DoTransactionsRollbackOnParentRollback() //Passes
{
SqlCeTestDatabase db = new SqlCeTestDatabase(@"<?xml version=""1.0"" encoding=""utf-8""?>
<hibernate-mapping xmlns=""urn:nhibernate-mapping-2.2"" assembly=""Tests"" namespace=""Tests"">
<class name=""Tests.TestEntity, Tests"" table=""TestEntities"" >
<id name=""Id"" column=""Id"" type=""Int32"" />
</class>
</hibernate-mapping>", "Test");
db.SetUpNewDatabase();
using (var tx = new TransactionScope(TransactionScopeOption.Required))
{
using (var childTransaction = new TransactionScope(TransactionScopeOption.Required))
{
using (var session = db.CreateSession())
{
session.Save(new TestEntity
{
});
}
childTransaction.Complete();
}
//no complete so should rollback
}
using (var session = db.CreateSession())
{
Assert.AreEqual(0, session.CreateCriteria<TestEntity>().List<TestEntity>().Count());
}
}
}
public class TestEntity
{
public virtual int Id { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment