简体   繁体   English

Nhibernate架构-通用Nhibernate信息库,可服务于多种类型

[英]Nhibernate Architecture - Generic Nhibernate Repository to serve many different types

I am looking to get some feedback on how I can improve my design. 我希望获得一些有关如何改进设计的反馈。 Specifically, I don't want to have to create a new repository object for each of my domain objects but I also do not want to rewrite the Session and Transaction logic over and over. 具体来说,我不想为每个域对象创建一个新的存储库对象,但是我也不想一遍又一遍地重写Session和Transaction逻辑。

To alleviate the need to write the code to obtain a new session and transation for every database transaction I make I created and generic abstract class that looks like this: 为了减轻编写代码以获取我创建的每个数据库事务的新会话和事务的需求,并创建了通用抽象类,如下所示:

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

Thats great but then I have to create a repository for each of my domain entities like so: 很好,但是随后我必须为每个域实体创建一个存储库,如下所示:

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

I could potentially have many of these. 我可能会有很多这样的东西。 Can someone suggest a different approach? 有人可以建议其他方法吗?

Thanks in advance. 提前致谢。

Your repositories should (in general) not open sessions or perform transactions. 通常,您的存储库不应打开会话或执行事务。 That should be done in a service layer or the UI. 这应该在服务层或UI中完成。 With your current design there's no way to have multiple repositories participate in the same transaction. 使用当前的设计,无法让多个存储库参与同一笔交易。 You can accomplsh this by requiring the ISession in the repository constructor. 您可以通过在存储库构造函数中要求ISession来实现此目的。

I also dislike the one repository per object model, a better approach is to logically group together common repository functions. 我还不喜欢每个对象模型一个存储库,更好的方法是将通用存储库功能逻辑地组合在一起。 For example, a CompanyRepository would have methods for working with companies and related data -- CompanyType, CompanyStatus, etc. 例如,CompanyRepository将具有用于处理公司和相关数据的方法-CompanyType,CompanyStatus等。

The way which I have seen this done (and how I do this) is to establish an interface, Create a Nhiberate class which realises this interface (Repository Pattern) 我看到的完成方式(以及执行方式)是建立一个接口,创建一个实现该接口的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.rosscode.com/blog/index.php?title=the_repository_pattern_andash_iarsquo_m_&more=1&c=1&tb=1&pb=1

also the use of the Specification pattern allows for queries to be passed to the repository. 规范模式的使用还允许将查询传递到存储库。 more information can be found here: 更多信息可以在这里找到:

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

things to note is the session is created elsewhere and then injected (passed) into the repositories, I use an IoC container such as Windsor to do this. 需要注意的是,会话是在其他地方创建的,然后注入(传递)到存储库中,我使用诸如Windsor之类的IoC容器来执行此操作。

HTH HTH

Maybe I am not understanding your question? 也许我不明白您的问题? You seem to be asking more about how to implement the generics so you do not have to create a type specific class for each object rather than asking an nhibernate question. 您似乎在询问有关如何实现泛型的更多信息,因此您不必为每个对象创建特定于类型的类,而无需询问nhibernate问题。

Here is a simple Repository that accepts any type T. You just remove the T from the class signature and instantiate. 这是一个接受任何类型T的简单存储库。您只需从类签名中删除T并实例化即可。 But keep in mind this is little more than a session wrapper, more a Unit of work than a repository. 但是请记住,这不过是一个会话包装程序,一个工作单元而不是一个存储库。 Implementing queries will require some work to try to make generic. 实现查询将需要一些工作以尝试使其通用。 You could use something like this as a base class for a subtype where you need complex queries and also as a standalone instance if you only support very basic queries for other objects. 您可以将类似这样的东西用作需要复杂查询的子类型的基类,也可以将其用作独立实例(如果您仅支持对其他对象的基本查询)。

/// <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;
    }

}

} }

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

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