【问题标题】:Nhibernate transactions:Avoiding Nhibernate dependency in the service layerNhibernate 事务:避免服务层中的 Nhibernate 依赖
【发布时间】:2010-03-30 18:17:51
【问题描述】:

Nhibernate 专家提倡的做法之一是做all actions in inside a transaction.

在典型的 3 层 Web 架构中,Nhibernate 的依赖仅限于数据层。

在这种情况下可以使用

  using (var tr = NHibernateSession.Current.BeginTransaction()) {

在控制器级别。这不会给服务层带来对 Nhibernate 的依赖吗?

【问题讨论】:

    标签: c# .net nhibernate transactions s#arp-architecture


    【解决方案1】:

    解决此问题的一种方法是将 NHibernate 会话和事务语义包装在您自己的抽象接口/实现类中。这样,如果您想说,切换到 Linq2Sql,您可以创建 L2S 实现。但是,这仍然意味着事务语义仍将在服务层中,而不是 NHibernate 特定的调用。谷歌IRepository<T> 有很多如何做到这一点的例子。

    但是,如果您不打算在未来切换您的 ORM,有人可能会争辩说,在服务层中使用 NHibernate 不一定是一件坏事,因为 NHibernate 本身就是对数据层的抽象。

    【讨论】:

    • +1 如果您发现自己需要在项目中间切换 ORM,那么您遇到的问题比这更大。
    • +1 我们实际上确实切换了 ORM(iBatis -> NHibernate),很明显我们很早就需要进行切换。
    • 事实是我正处于从亚音速到休眠状态的过程中。这虽然不常见,但也不少见。通过将所有 NH 依赖项放在数据层中,从层架构来看,事情看起来很整洁。
    • 我认为这归结为是否要进行以下权衡:您可以通过存储库模式抽象您的 ORM 以在您的服务层中获得 ORM 无知,但权衡是您将失去您的一些 ORM 的最佳功能,因为从 ORM 到 ORM 的功能非常强大。使用 NHibernate,您将放弃未来的查询、多查询、批量插入等......这里没有明确的对错,而是为了满足您的最终目标而做出的选择。
    【解决方案2】:

    我也想这样做,但由于时间不足和一些 YAGNI,我还没有确定一个方法。

    这是一些我尚未测试的代码,但改编自开源 SharpArch 项目。我非常喜欢这个界面,但我可能稍微改变了 NHib 的实现,因为 SharpArch 的存储库实现有一些我不喜欢的地方,但你可以自己判断。

    当然,使用 NHib session.BeginTransaction() 会引入 NHib 依赖项,并且不将其抽象出来似乎与抽象出 IRepository 和其他所有内容不一致。我对您得出的有用的交易抽象非常感兴趣。

    HTH,
    浆果

    public interface IDbContext {
        void CommitChanges();
        IDisposable BeginTransaction();
        void CommitTransaction();
        void RollbackTransaction();
    }
    
    public class DbContext : IDbContext {
        private readonly ISession _session;
    
        public DbContext(ISession session)
        {
            Check.RequireNotNull<ISession>(session);
            _session = session;
        }
    
        public void CommitChanges() { _session.Flush(); }
    
        public IDisposable BeginTransaction() { return _session.BeginTransaction(); }
    
        public void CommitTransaction() { _session.Transaction.Commit(); }
    
        public void RollbackTransaction() { _session.Transaction.Rollback(); }
    
    }
    

    【讨论】:

    • 您是否考虑过从 idisposable 实现 idbcontext
    【解决方案3】:

    打电话给一些像这样散布的静态单身人士对我来说似乎不是一个好主意。或许最好添加对您自己的“ITransactionFactory”的依赖,并将 NHibernate 特定代码留在 TransactionFactory 实现中。

    特别是对于 SharpArchitecture,有一个 TransactionAttribute 操作过滤器,旨在将您的操作方法包装在事务中。

    关于 NHibernate 的程序集引用,我个人不会担心。

    【讨论】:

    • 不幸的是,TransactionAttribute 是 web.mvc 的 actionfilter 属性。将需要对其进行更改以使用网络表单
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    相关资源
    最近更新 更多