这个模型是一个很好的管理模式UOW / Repository与NHibernate?

时间:2014-06-10 08:14:11

标签: c# nhibernate repository repository-pattern unit-of-work

在StackOverflow和google上搜索我发现了许多不同的实现,但没有一个确实让我信服,每个都有一些小的缺陷阻止我使用它。所以我试着创建自己的版本,想知道你的想法。

基本上所有内容都基于使用以实体框架风格构建的接口和UnitOfWork模式,即使我使用NHibernate作为实现。

希望拥有绝对通用的接口,因此可以同时容纳EF NH我的UoW不会暴露这两个存储库的任何特定概念,例如会话或事务

这是用法:

using (IUnitOfWork uow = new NHUnitOfWork())
        {
            uow.StartOperation();
            Class1 c1 = _uow.Class1Repo.Read<Class1>(idClasse1);
            c1.Desc = "edited";
            uow.Class1Repo.Update(c1);
        }

当然可以使用依赖注入来避免新实例

这些是接口:

public interface IUnitOfWork : IDisposable{
    void StartOperation();
    void SaveAll();
    void DiscardChanges();
    void OpenConnection();
    void CloseConenction();

    IClass1Repository Class1Repo { get; }
            // All other repository here
}

此时我创建了我的通用存储库的基本接口,其中包含必须提供的所有操作(如果您希望可以创建通用存储库,以便将读取操作与写入操作区分开来,以便您可以使用对于没有预见到变化的对象的有限权限,但我不需要这种类型)

public interface IRepoBase<T> : IDisposable where T : class  {
        void Create(T obj);
        T Read<T>(object id);
        void Update(T obj);
        void Delete(T obj);
}

单个对象的所有剩余读取操作将在其特定存储库中进行管理

public interface IClass1Repository : IDisposable, IRepoBase<Class1> 
{
    IEnumerable<Class1> FindAll();
    string GetDescription();
}

查询的所有条件和过滤器将使用更具体的方法直接进入存储库,为什么不使用它IEnumerable IQueryable。通过这种方式,他们甚至没有链接到Linq

public class NHUnitOfWork: IUnitOfWork{
    private ITransaction _transaction;
    private NHSessionFactory _nhHelper;
    private ISession _session;
    public IClass1Repository Class1Repo { get; private set; }

    public NHUnitOfWork(NHSessionFactory nhHelper)      {
        _nhHelper = nhHelper ?? new NHSessionFactory();
        InitializeSession();        }

    public NHUnitOfWork()       {
        _nhHelper = new NHSessionFactory();
        InitializeSession();        }

    private void InitializeSession()        {
        if (_session == null)
               _session = _nhHelper.OpenSession();
        Class1Repo = new Class1Repository(this._session);
                    // All other repository here    }

    public void StartOperation()    {
        InitializeSession();
        _transaction = _session.BeginTransaction(); }

    public void SaveAll()   {           
        if (_transaction != null)       {
            _transaction.Commit();
            _transaction = null;    }   }

    public void DiscardChanges()    {
        Contract.Ensures(_session.Transaction.IsActive == false);
        if (_transaction != null)       {
            _transaction.Rollback();
            _transaction = null;    }   }


    public void OpenConnection()        {
        InitializeSession();        }

    public void CloseConnection()   {
        if (_transaction != null)   {
            _transaction.Dispose();
            _transaction = null;    }

        if (_session != null)   {
            _session.Dispose();
            _session = null;    }
    }

    // Disposable pattern here
}

OpenConnection和CloseConenction隐藏了nhibernate会话,而StartOperation,SaveAll和DiscardChanges隐藏了原子操作的概念(事务)

BaseRepository的NH实现:

class NHRepoBase<T> : IDisposable,  IRepoBase<T> where T : class
{
    protected ISession _session;
    public NHRepoBase(ISession session)
    {_session = session;    }

    public void Create(T obj)
    { _session.SaveOrUpdate(obj); }

    public void Update(T obj)
    { _session.Merge<T>(obj); }

    public void Delete(T obj)
    { _session.Delete(obj); }

    public T Read<T>(object id)
    { return _session.Get<T>(id); }

    private bool disposed = false;
    protected virtual void Dispose(bool disposing)  {
        if (!this.disposed){
            if (disposing)
             _session.Dispose();                
        }
        this.disposed = true;
    }
    public void Dispose()   {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

一个简单的特定存储库:

class Class1Repository : NHRepoBase<Class1>, IClass1Repository, IDisposable {
    public Class1Repository(ISession session) : base(session) { }

    public IEnumerable<Class1> FindAll()
    { return _session.QueryOver<Class1>().List();    }

    public string GetDescription()
    { return _session.QueryOver<Class1>().Select(c => c.Desc).SingleOrDefault<string>(); }
}

提前感谢您对我的实施提出任何建议或反馈

0 个答案:

没有答案