GenericRepository
There are other examples on the web, but I usually need paged result sets- hence FindPage (paged get), and Count.
- I use a transaction wrapper called TransactionRequired. Others use ITransaction transaction = Session.BeginTransaction()). In practice, normal TransactionScope works well.
- You might want to use IoC to inject the SessionManager via the constructor rather than rely on a static/ singleton object.
- See notes on HQL/ICriteria
using System;
using System.Collections.Generic;
using NHibernate;
namespace Northwind
{
/// <summary>
/// A generic repository. Normally this would be a base class of customized entity repositories- not directly exposed.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <remarks>
/// All operations are wrapped with <see cref="TransactionRequired"/>. If there is NO open transaction, they open a transaction and commit immediately. If there is an open transaction, nothing is commited, so you should commit at a higher level.
/// </remarks>
public class GenericRepository<T> where T : new()
{
protected ISession Session
{
get { return SessionManager.Instance.Session; }
}
#region Read
/// <summary>
/// Loads the specified id. Throws an exception if not in database.
/// </summary>
public T Load(object id)
{
using (TransactionRequired transaction = new TransactionRequired())
{
return Session.Load<T>(id);
}
}
/// <summary>
/// Gets the Id. Returns null if there is no matching row
/// </summary>
public T GetById(object id)
{
using (TransactionRequired transaction = new TransactionRequired())
{
return Session.Get<T>(id);
}
}
/// <summary>
/// Finds all records. Consider <see cref="FindPage"/> for large result sets.
/// </summary>
public ICollection<T> FindAll()
{
using (TransactionRequired transaction = new TransactionRequired())
{
return Session.CreateCriteria(typeof(T)).List<T>();
}
}
/// <summary>
/// Counts the number of records.
/// </summary>
public int Count()
{
ICriteria criteria = Session.CreateCriteria(typeof(T));
using (TransactionRequired transaction = new TransactionRequired())
{
return criteria.SetProjection(NHibernate.Criterion.Projections.RowCount()).UniqueResult<int>();
}
}
/// <summary>
/// Finds records by page.
/// </summary>
/// <param name="pageStartRow">The page start row.</param>
/// <param name="pageSize">Size of the page.</param>
public IList<T> FindPage(int pageStartRow, int pageSize)
{
ICriteria criteria = Session.CreateCriteria(typeof(T));
criteria.SetFirstResult(pageStartRow);
criteria.SetMaxResults(pageSize);
using (TransactionRequired transaction = new TransactionRequired())
{
return criteria.List<T>();
}
}
/// <summary>
/// Finds records by page, sorted.
/// </summary>
public IList<T> FindSortedPage(int pageStartRow, int pageSize, string sortBy, bool descending)
{
ICriteria criteria = Session.CreateCriteria(typeof(T));
if (descending)
criteria.AddOrder(NHibernate.Criterion.Order.Desc(sortBy));
else
criteria.AddOrder(NHibernate.Criterion.Order.Asc(sortBy));
criteria.SetFirstResult(pageStartRow);
criteria.SetMaxResults(pageSize);
using (TransactionRequired transaction = new TransactionRequired())
{
return criteria.List<T>();
}
}
#endregion
#region Update
/// <summary>
/// Saves the specified object within a transaction.
/// </summary>
public void Save(T entity)
{
using (TransactionRequired transaction = new TransactionRequired())
{
Session.Save(entity);
transaction.Commit(); //flush to database
}
}
/// <summary>
/// Saves the specified object within a transaction.
/// </summary>
public void SaveOrUpdate(T entity)
{
using (TransactionRequired transaction = new TransactionRequired())
{
Session.SaveOrUpdate(entity);
transaction.Commit(); //flush to database
}
}
/// <summary>
/// Deletes the specified object within a transaction.
/// </summary>
public void Delete(T entity)
{
using (TransactionRequired transaction = new TransactionRequired())
{
Session.Delete(entity);
transaction.Commit(); //flush to database
}
}
#endregion
}
}