简体   繁体   English

通用存储库中的工作单元

[英]Unit Of Work in Generic Repository

I want to move my Unit of work away from my business logic. 我想将工作单元从业务逻辑中移开。

In Infrastructure.Data I have 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
}

In Intrastructure.DependencyInjectrion I have: 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<>));

    }

Then in my service I would do something like this: 然后在我的服务中,我将执行以下操作:

Web.UI.Services.CompanyService

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

Would it be a better practice to call _unitOfWork.Commit() or _unitOfWork.Rollback() in the eneric Repository rather than in the in the Service layer? 在能量Repository而不是在Service层中调用_unitOfWork.Commit()_unitOfWork.Rollback()是更好的做法吗?

I was thinking of improving the generic Repository by injecting the IUnitOfWork into it while adding some additional error handling in too. 我当时正在考虑通过IUnitOfWork注入IUnitOfWork来改进通用Repository ,同时IUnitOfWork添加一些其他错误处理。

If this is not a good approach, can someone give me some direction to improve this? 如果这不是一个好的方法,有人可以给我一些指导以改进它吗? Note: I do want to keep repository pattern in case we choose to switch ORM in a few years time. 注意:我确实想保留repository pattern ,以防我们选择在几年后切换ORM

Managing transactions in the repository is definitely not the standard way to do it, as it removes the possibility to implement business logic that spans multiple repositories (or multiple actions on the same repository) and is required to be executed atomically. 在存储库中管理事务绝对不是实现此操作的标准方法,因为它消除了实现跨越多个存储库(或同一存储库上的多个操作)并需要原子执行的业务逻辑的可能性。

I would try to keep the transaction management on the top-most layer that makes sense, ie that does not impair your ability to re-use business logic (including transaction management) if you decided to host your application in a different environment for example. 我会尝试将事务管理放在有意义的最顶层,即,例如,如果您决定将应用程序托管在不同的环境中,则这不会损害您重用业务逻辑(包括事务管理)的能力。 This would seem to be the service layer in your case; 在您的情况下,这似乎是服务层; you could also distinguish between different types of services as done in Domain-Driven Design where there is a difference between application services and domain services . 您还可以区分不同类型的服务,如在域驱动设计中完成的那样,其中应用程序服务域服务之间存在差异。 The application services might orchestrate multiple domain services and handle the management of transactions and potentially the unit of work). 应用程序服务可以协调多个域服务,并处理事务管理以及可能的工作单元管理。

Hope this helps a bit. 希望这个对你有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM