开发者

Nhibernate Architecture - Generic Nhibernate Repository to serve many different types

I am looking to get some feedback o开发者_C百科n 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.

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. 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.

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.


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)

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

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.

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.

Here is a simple Repository that accepts any type T. You just remove the T from the class signature and instantiate. 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;
    }

}

}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜