通用存储库中的工作单元

时间:2015-03-05 21:58:44

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

我想让我的工作单元远离我的业务逻辑。

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 ();
    }

更好的做法是在通用_unitOfWork.Commit()而不是_unitOfWork.Rollback()图层中调用RepositoryService吗?

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

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

1 个答案:

答案 0 :(得分:1)

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

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

希望这有点帮助。