Nhibernate Architecture - 通用Nhibernate存储库,可以提供多种不同类型的服务

时间:2010-10-02 04:10:19

标签: c# nhibernate architecture

我希望得到一些关于如何改进设计的反馈。具体来说,我不想为每个域对象创建一个新的存储库对象,但我也不想一遍又一遍地重写Session和Transaction逻辑。

为了减少编写代码以获取新会话和转换的需要,我创建的每个数据库事务和通用抽象类看起来像这样:

 public class AbstractNHibernate<T> where T : class
{

    public void Add<T>(T entity) 
    { 
        using(ISession session = NHibernateHelper.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            session.Save(entity);
            transaction.Commit();
        }
    }
}

这很棒,但后来我必须为每个域实体创建一个存储库,如下所示:

    public class ConnectionModel : AbstractNHibernate<Connection>
    {
        public void SaveConnection(Connection conn)
{
Add(conn);
}
    }

我可能有很多这些。有人可以提出不同的方法吗?

提前致谢。

3 个答案:

答案 0 :(得分:2)

您的存储库(通常)不应该打开会话或执行事务。这应该在服务层或UI中完成。使用您当前的设计,无法让多个存储库参与同一事务。您可以通过在存储库构造函数中要求ISession来完成此任务。

我也不喜欢每个对象模型的一个存储库,更好的方法是将公共存储库函数逻辑地组合在一起。例如,CompanyRepository将具有处理公司和相关数据的方法 - CompanyType,CompanyStatus等。

答案 1 :(得分:0)

我看到这样做的方式(以及我如何做)是建立一个接口,创建一个实现这个接口的Nhiberate类(存储库模式)

http://www.rosscode.com/blog/index.php?title=the_repository_pattern_andash_iarsquo_m_&more=1&c=1&tb=1&pb=1

使用规范模式也允许将查询传递到存储库。更多信息可以在这里找到:

http://www.mostlyclean.com/category/NHibernate.aspx

需要注意的是会话是在别处创建的,然后注入(传递)到存储库中,我使用像Windsor这样的IoC容器来执行此操作。

HTH

答案 2 :(得分:0)

也许我不理解你的问题?您似乎更多地询问如何实现泛型,因此您不必为每个对象创建特定于类型的类,而不是询问nhibernate问题。

这是一个接受任何类型T的简单存储库。您只需从类签名中删除T并实例化。但请记住,这只不过是一个会话包装器,更像是一个工作单元而不是一个存储库。实现查询将需要一些工作来尝试制作通用。您可以使用类似这样的东西作为您需要复杂查询的子类型的基类,如果您只支持对其他对象的非常基本的查询,也可以使用它作为独立实例。

/// <summary>
/// Repository defines simple class with standard methods
/// to accept and operate on any type.
/// </summary>
public class Repository
{
    private ISession _session;

    public ISession Session
    {
        get { return _session; }
    }


    /// <summary>
    /// Save an entity.
    /// </summary>
    public void Save<T>(T entity)
    {
        Reconnect(_session);
        try
        {
            _session.Save(entity);
        }
        finally
        {
            Disconnect(_session);
        }
    }

    /// <summary>
    /// Update an entity
    /// </summary>
    public void Update<T>(T entity)
    {
        Reconnect(_session);
        try
        {
            _session.Update(entity);
        }
        finally
        {
            Disconnect(_session);
        }
    }

    /// <summary>
    /// Delete an entity
    /// </summary>
    public void Delete<T>(T entity)
    {
        Reconnect(_session);
        try
        {
            _session.Delete(entity);
        }
        finally
        {
            Disconnect(_session);
        }
    }

    /// <summary>
    /// Retrieve an entity
    /// </summary>
    public T GetById<T>(Guid id)
    {
        Reconnect(_session);
        try
        {
            return _session.Get<T>(id);
        }
        finally
        {
            Disconnect(_session);
        }
    }

    /// <summary>
    /// Method for flushing the session.
    /// </summary>
    public void Flush()
    {
        Reconnect(_session);
        try
        {
            _session.Flush();
            _session.Clear();
        }
        finally
        {
            Disconnect(_session);
        }
    }

    /// <summary>
    /// Reconnect to the session. Accept parameter so we can use anywhere.
    /// </summary>
    public void Reconnect(ISession session)
    {
        if (!session.IsConnected)
        {
            session.Reconnect();
        }
    }

    /// <summary>
    /// Disconnect from the session.  Accept parameter so we can use anywhere.
    /// </summary>
    public void Disconnect(ISession session)
    {
        if (session.IsConnected)
        {
            session.Disconnect();
        }
    }

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

}

}