【问题标题】:Unit Of Work in Generic Repository通用存储库中的工作单元
【发布时间】:2015-03-05 21:58:43
【问题描述】:

我想将我的工作单元从我的业务逻辑中移开。

Infrastructure.Data 我有

NHibernateHelper

public class NHibernateHelper
{
    private ISessionFactory _sessionFactory;
    private readonly string _connectionString;

    public NHibernateHelper (string connectionString)
    {
        if (string.IsNullOrEmpty (connectionString))
            throw new HibernateConfigException ("ConnectionString in Web.config is not set.");

        _connectionString = connectionString;
    }

    public ISessionFactory SessionFactory {
        get {
            return _sessionFactory ?? (_sessionFactory = InitializeSessionFactory ());
        }
    }

    private ISessionFactory InitializeSessionFactory ()
    {
        return Fluently.Configure ()
            .Database (PostgreSQLConfiguration.Standard.ConnectionString (_connectionString).
                Dialect ("NHibernate.Dialect.PostgreSQL82Dialect"))
        // Use class mappings
            .Mappings (m => m.FluentMappings.AddFromAssembly (Assembly.GetExecutingAssembly ()))
        // Will Update and create tables if does not exist
            .ExposeConfiguration (cfg => new SchemaUpdate (cfg).Execute (true, true))
            .BuildSessionFactory ();
    }
}

UnitOfWork

public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;

    public ISession Session { get; private set; }

    public UnitOfWork (ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
        Session = _sessionFactory.OpenSession ();
        Session.FlushMode = FlushMode.Auto;
        _transaction = Session.BeginTransaction (IsolationLevel.ReadCommitted);
    }

    public void Commit ()
    {
        if (!_transaction.IsActive) {
            throw new InvalidOperationException ("Oops! We don't have an active transaction");
        }
        _transaction.Commit ();
    }

    public void Rollback ()
    {
        if (_transaction.IsActive) {
            _transaction.Rollback ();
        }
    }

    public void Dispose ()
    {
        if (Session.IsOpen) {
            Session.Close ();
            Session = null;
        }
    }
}

Repository

public class Repository<TEntity> : IReadWriteRepository<TEntity>
    where TEntity : class
{
    private readonly ISession _session;

    public Repository (ISession session)
    {
        _session = session;
    }

    #region IWriteRepository

    public bool Add (TEntity entity)
    {
        _session.Save (entity);
        return true;
    }

    public bool Add (System.Collections.Generic.IEnumerable<TEntity> entities)
    {
        foreach (TEntity entity in entities) {
            _session.Save (entity);
        }
        return true;
    }

    public bool Update (TEntity entity)
    {
        _session.Update (entity);
        return true;
    }

    public bool Update (System.Collections.Generic.IEnumerable<TEntity> entities)
    {
        foreach (TEntity entity in entities) {
            _session.Update (entity);
        }
        return true;
    }

    public bool Delete (TEntity entity)
    {
        _session.Delete (entity);
        return true;
    }

    public bool Delete (System.Collections.Generic.IEnumerable<TEntity> entities)
    {
        foreach (TEntity entity in entities) {
            _session.Delete (entity);
        }
        return true;
    }

    #endregion

    #region IReadRepository

    public System.Linq.IQueryable<TEntity> All ()
    {
        return _session.Query<TEntity> ();
    }

    public TEntity FindBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
    {
        return FilterBy (expression).SingleOrDefault ();
    }

    public TEntity FindBy (object id)
    {
        return _session.Get<TEntity> (id);
    }

    public System.Linq.IQueryable<TEntity> FilterBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
    {
        return All ().Where (expression).AsQueryable ();
    }

    #endregion
}

Intrastructure.DependencyInjectrion 我有:

    public void RegisterServices (SimpleInjector.Container container)
    {

        var connectionSettings = ConfigurationManager.ConnectionStrings ["Connection"];

        container.RegisterPerWebRequest<ISessionFactory> (() => {
            NHibernateHelper objNHibernate = new NHibernateHelper (connectionSettings.ConnectionString);
            return objNHibernate.SessionFactory;
        });


        container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork> ();

        container.RegisterPerWebRequest<ISession> (() => {

            UnitOfWork unitOfWork = (UnitOfWork)container.GetInstance<IUnitOfWork> ();
            return unitOfWork.Session;

        });

        container.RegisterOpenGeneric (typeof(IReadWriteRepository<>), typeof(Repository<>));

    }

然后在我的服务中,我会做这样的事情:

Web.UI.Services.CompanyService

    public void CreateNewCompany (Company company)
    {
        if (_companyRepository.Add (company))
            _unitOfWork.Commit ();
        else
            _unitOfWork.Rollback ();
    }

Repository 中调用_unitOfWork.Commit()_unitOfWork.Rollback() 会比在Service 层中更好吗?

我正在考虑通过将IUnitOfWork 注入其中来改进通用Repository,同时添加一些额外的错误处理。

如果这不是一个好方法,有人可以给我一些改进的方向吗?注意:我确实想保留repository pattern,以防我们选择在几年后切换ORM

【问题讨论】:

    标签: c# asp.net-mvc-4 repository-pattern unit-of-work onion-architecture


    【解决方案1】:

    在存储库中管理事务绝对不是执行此操作的标准方法,因为它消除了实现跨多个存储库(或同一存储库上的多个操作)的业务逻辑的可能性,并且需要以原子方式执行。

    如果您决定将应用程序托管在不同的环境中,我会尽量将事务管理保留在最顶层,这不会影响您重用业务逻辑(包括事务管理)的能力例如。在您的情况下,这似乎是服务层;您还可以像在领域驱动设计中所做的那样区分不同类型的服务,其中 应用程序服务域服务 之间存在差异。 应用程序服务可能会编排多个域服务并处理事务管理和潜在的工作单元)。

    希望这会有所帮助。

    【讨论】:

    • 那是有道理的。你会说目前执行工作单元的方式很好吗?并保持原样?我会去读更多的 DDD,我想我错过了什么哈哈
    • 我会说工作单元的实现对我来说总体上看起来不错。我想每个工作单元都会创建一个实例(不管是什么,可能是一个 HTTP 请求)。您可能唯一需要考虑的事情是您是否要实现一个处理工作单元的终结器,以及是否要在处理时检查活动事务(如果有活动事务,则执行回滚并记录错误或其他内容) ; 这将阻止打开的交易 - 不确定Session.Close() 是否已经处理了这个问题。
    • 另外,我个人会稍微不同地使用工作单元,如果我可以确定您发布的服务代码中没有任何更改,我不会回滚事务。在 RDBMS 上,提交总是比回滚便宜。
    • 我已经更新了帖子。我使用RegisterPerRequest 方法作为简单注入器依赖注入的一部分。我会去检查我的代码并进行一些更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 2019-02-25
    • 2015-01-20
    • 2013-04-23
    相关资源
    最近更新 更多