リポジトリは次のようになります
public abstract class Repository<TEntity> : IRepository<TEntity>
where TEntity : Entity
{
#region Members
protected IContext Context;
#endregion
#region Constructor
/// <summary>
/// Create a new instance of repository
/// </summary>
/// <param name="context">Associated Unit Of Work</param>
protected Repository(IContext context)
{
if (context == null)
throw new ArgumentNullException("context");
Context = context;
}
#endregion
#region IRepository Members
public virtual TEntity Add(TEntity item)
{
return Context.Add(item);
}
public virtual void Remove(TEntity item)
{
Set().Remove(item);
}
public virtual void Remove(Guid id)
{
var persisted = Get(id);
if (persisted == null) throw new Exception(string.Format("Illegal parameter id:{0}", id));
Remove(persisted);
}
public virtual void Update(TEntity item)
{
Context.Update(item);
}
public virtual TEntity Get(Guid id)
{
return (id != Guid.Empty) ? Query().SingleOrDefault(i => i.Id == id) : null;
}
public virtual IEnumerable<TEntity> GetAll()
{
return Query();
}
public TEntity FirstOrDefaultMatching(ISpecification<TEntity> specification)
{
return AllMatching(specification).FirstOrDefault();
}
public virtual IEnumerable<TEntity> AllMatching(ISpecification<TEntity> specification)
{
return Query().Where(specification.SatisfiedBy());
}
public virtual IEnumerable<TEntity> GetPaged<TKProperty>(int pageIndex, int pageCount,
Expression<Func<TEntity, TKProperty>> orderByExpression, bool ascending)
{
var set = Query();
if (ascending)
{
return set.OrderBy(orderByExpression)
.Skip(pageCount * pageIndex)
.Take(pageCount)
.AsEnumerable();
}
return set.OrderByDescending(orderByExpression)
.Skip(pageCount * pageIndex)
.Take(pageCount)
.AsEnumerable();
}
public virtual IEnumerable<TEntity> GetFiltered(Expression<Func<TEntity, bool>> filter)
{
return Query().Where(filter).AsEnumerable();
}
public IQueryable<TEntity> CreateSet()
{
return Context.CreateSet<TEntity>();
}
public bool AnyMatching(ISpecification<TEntity> specification)
{
return Query().Any(specification.SatisfiedBy());
}
#endregion
#region Protected Methods
protected virtual IQueryable<TEntity> Query()
{
return Context.CreateSet<TEntity>().Where(EntitySpecification<TEntity>.ValidEntity().SatisfiedBy());
}
#endregion
}
EF の場合のコンテキストは DBContext であり、NHibernate の場合は Session です。
これがNHibernateへの私のIContext実装です
public class NHibernateEntityContext : IContext
{
private readonly ISession _session;
private static ISessionFactory _sessionFactory;
public NHibernateEntityContext()
{
if (_sessionFactory == null)
{
//Your NHibernate Configuration
//_sessionFactory = Fluently.Configure()
}
_session = _sessionFactory.OpenSession();
_session.FlushMode = FlushMode.Auto;
}
#region Implementation of IDisposable
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public void Dispose()
{
if (_session.IsOpen)
_session.Close();
}
#endregion
public IUnitOfWork BeginTransaction()
{
return new UnitOfWork(_session);
}
#region Implementation of IContext
public IQueryable<TEntity> CreateSet<TEntity>() where TEntity : class
{
return _exceptionHandler.TryCatch(() => _session.Query<TEntity>());
}
/// <summary>
/// Add this item into the Context
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="item">The item </param>
public TEntity Add<TEntity>(TEntity item) where TEntity : class
{
return _exceptionHandler.TryCatch(() =>
{
_session.Save(item);
return item;
});
//return _session.Merge(item);
}
/// <summary>
/// Set object as modified
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="item">The entity item to set as modifed</param>
public void Update<TEntity>(TEntity item) where TEntity : class
{
_exceptionHandler.TryCatch(() => _session.Merge(item));
}
public void Delete<TEntity>(TEntity item) where TEntity : class
{
_exceptionHandler.TryCatch(() => _session.Delete(item));
}
#endregion
}
私のUnitofWorkはこのようなものです
public class UnitOfWork : IUnitOfWork
{
private readonly ITransaction _transaction;
internal UnitOfWork(ISession session)
{
_transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("Oops! We don't have an active transaction");
}
_transaction.Commit();
}
public void RollbackChanges()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
public void Dispose()
{
_transaction.Dispose();
}
}
そして、次のように使用できます。
using (var trans = UnitOfWorkFactory.Create())
{
...
trans.Commit();
}