在存储库中公开事务.NHibernate

本文关键字:事务 NHibernate 存储 | 更新日期: 2023-09-27 18:25:45

所以目前我有这样一个存储库实现:

public class Repository<T> : IRepository<T> where T : AbstractEntity<T>, IAggregateRoot
{
    private ISession session;
    public Repository(ISession session)
    {
        this.session = session;
    }
    public T Get(Guid id)
    {            
        return this.session.Get<T>(id);            
    }
    public IQueryable<T> Get(Expression<Func<T, Boolean>> predicate)
    {
        return this.session.Query<T>().Where(predicate);            
    }
    public IQueryable<T> Get()
    {
        return this.session.Query<T>();            
    }
    public T Load(Guid id)
    {
        return this.session.Load<T>(id);
    }
    public void Add(T entity)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Save(entity);
            transaction.Commit();
        }
    }
    public void Remove(T entity)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Delete(entity);
            transaction.Commit();
        }
    }
    public void Remove(Guid id)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Delete(this.session.Load<T>(id));
            transaction.Commit();
        }
    }
    public void Update(T entity)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Update(entity);
            transaction.Commit();
        }
    }
    public void Update(Guid id)
    {            
        using(var transaction = this.session.BeginTransaction())
        {
            this.session.Update(this.session.Load<T>(id));
            transaction.Commit();
        }
    }
}

然后我像这样使用Ninject模块。

public class DataAccessModule : Ninject.Modules.NinjectModule
{
    public override void Load()
    {
        this.Bind<ISessionFactory>()
            .ToMethod(c => new Configuration().Configure().BuildSessionFactory())
            .InSingletonScope();
        this.Bind<ISession>()
            .ToMethod(ctx => ctx.Kernel.TryGet<ISessionFactory>().OpenSession())
            .InRequestScope();
        this.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
    }
}

模式导出和更新的调用类似于测试:

[TestFixture]
public class SchemaManipulations
{
    [Test]
    [Ignore]
    public void CreateDatabaseSchema()
    {
        new SchemaExport(new Configuration().Configure()).Create(false, true);
    }
    [Test]
    [Ignore]
    public void UpdateDatabaseSchema()
    {
        new SchemaUpdate(new Configuration().Configure()).Execute(false, true);
    }
}

我保持"干净"我的域层:验证逻辑是用FluentValidation实现的,它不知道NHibernate,也不知道其他任何东西。

这对我来说似乎很完美……直到我想知道如何实现版本并发。我选择使用optimistic-locking,至于为NH正确映射它,这不是问题。我需要知道如何处理事务,在编辑locked项目时如何通知用户?

因此,针对长会话的版本并发控制又出现了一个问题。NHibernate。ASP.NET MVC,据说不建议在Repository上公开事务。

问题本身

我已经听说过SharpArchitectureUOW。这已经足够了。

但我对我的数据访问策略解决方案中提供的问题很感兴趣:这样使用它会面临什么错误/故障?

使用Kaleb PedersonNHibernate提出的事务和TransactionScope方法是否也是一种解决方案?

谢谢!

在存储库中公开事务.NHibernate

您将如何编写这样的代码?

// Save both together or none of it
rep1.Save(newSomeEntity);
rep2.Save(SomeOtherEntity);

不在储存库中很容易

var rep1 = new Repository<SomeEntity>(session);
var rep2 = new Repository<SomeOtherEntity>(session);
using (var tx = session.BeginTransaction())
{
    try
    {
        rep1.Save(newSomeEntity);
        rep2.Save(SomeOtherEntity);
        tx.Commit();
    }
    catch (SomeException ex)
    {
        Handle(ex);
        tx.RollBack();
    }
}