通用存储库中的工作单元
Unit Of Work in Generic Repository
我想将我的工作单元从我的业务逻辑中移开。
在Infrastructure.Data
我有
NHibernateHelper
public class NHibernateHelper
{
private ISessionFactory _sessionFactory;
private readonly string _connectionString;
public NHibernateHelper (string connectionString)
{
if (string.IsNullOrEmpty (connectionString))
throw new HibernateConfigException ("ConnectionString in Web.config is not set.");
_connectionString = connectionString;
}
public ISessionFactory SessionFactory {
get {
return _sessionFactory ?? (_sessionFactory = InitializeSessionFactory ());
}
}
private ISessionFactory InitializeSessionFactory ()
{
return Fluently.Configure ()
.Database (PostgreSQLConfiguration.Standard.ConnectionString (_connectionString).
Dialect ("NHibernate.Dialect.PostgreSQL82Dialect"))
// Use class mappings
.Mappings (m => m.FluentMappings.AddFromAssembly (Assembly.GetExecutingAssembly ()))
// Will Update and create tables if does not exist
.ExposeConfiguration (cfg => new SchemaUpdate (cfg).Execute (true, true))
.BuildSessionFactory ();
}
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork (ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession ();
Session.FlushMode = FlushMode.Auto;
_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 Rollback ()
{
if (_transaction.IsActive) {
_transaction.Rollback ();
}
}
public void Dispose ()
{
if (Session.IsOpen) {
Session.Close ();
Session = null;
}
}
}
Repository
public class Repository<TEntity> : IReadWriteRepository<TEntity>
where TEntity : class
{
private readonly ISession _session;
public Repository (ISession session)
{
_session = session;
}
#region IWriteRepository
public bool Add (TEntity entity)
{
_session.Save (entity);
return true;
}
public bool Add (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Save (entity);
}
return true;
}
public bool Update (TEntity entity)
{
_session.Update (entity);
return true;
}
public bool Update (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Update (entity);
}
return true;
}
public bool Delete (TEntity entity)
{
_session.Delete (entity);
return true;
}
public bool Delete (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Delete (entity);
}
return true;
}
#endregion
#region IReadRepository
public System.Linq.IQueryable<TEntity> All ()
{
return _session.Query<TEntity> ();
}
public TEntity FindBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
{
return FilterBy (expression).SingleOrDefault ();
}
public TEntity FindBy (object id)
{
return _session.Get<TEntity> (id);
}
public System.Linq.IQueryable<TEntity> FilterBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
{
return All ().Where (expression).AsQueryable ();
}
#endregion
}
在 Intrastructure.DependencyInjectrion
我有:
public void RegisterServices (SimpleInjector.Container container)
{
var connectionSettings = ConfigurationManager.ConnectionStrings ["Connection"];
container.RegisterPerWebRequest<ISessionFactory> (() => {
NHibernateHelper objNHibernate = new NHibernateHelper (connectionSettings.ConnectionString);
return objNHibernate.SessionFactory;
});
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork> ();
container.RegisterPerWebRequest<ISession> (() => {
UnitOfWork unitOfWork = (UnitOfWork)container.GetInstance<IUnitOfWork> ();
return unitOfWork.Session;
});
container.RegisterOpenGeneric (typeof(IReadWriteRepository<>), typeof(Repository<>));
}
然后在我的服务中我会做这样的事情:
Web.UI.Services.CompanyService
public void CreateNewCompany (Company company)
{
if (_companyRepository.Add (company))
_unitOfWork.Commit ();
else
_unitOfWork.Rollback ();
}
在动态 Repository
中调用 _unitOfWork.Commit()
或 _unitOfWork.Rollback()
比在 Service
层中调用 _unitOfWork.Rollback()
更好吗?
我正在考虑通过将 IUnitOfWork
注入其中并添加一些额外的错误处理来改进通用 Repository
。
如果这不是一个好方法,有人可以给我一些改进的方向吗?注意:我确实想保留 repository pattern
,以防我们在几年后选择切换 ORM
。
在存储库中管理事务绝对不是标准方法,因为它消除了实现跨越多个存储库(或同一存储库上的多个操作)的业务逻辑的可能性,并且需要以原子方式执行。
我会尽量将事务管理保留在最顶层,这样才有意义,也就是说,如果您决定将应用程序托管在例如不同的环境。在您的情况下,这似乎是服务层;您还可以区分不同类型的服务,就像在领域驱动设计中所做的那样,其中 应用程序服务 和 领域服务 之间存在差异。 应用程序服务可能会编排多个域服务并处理事务管理和潜在的工作单元)。
希望对您有所帮助。
我想将我的工作单元从我的业务逻辑中移开。
在Infrastructure.Data
我有
NHibernateHelper
public class NHibernateHelper
{
private ISessionFactory _sessionFactory;
private readonly string _connectionString;
public NHibernateHelper (string connectionString)
{
if (string.IsNullOrEmpty (connectionString))
throw new HibernateConfigException ("ConnectionString in Web.config is not set.");
_connectionString = connectionString;
}
public ISessionFactory SessionFactory {
get {
return _sessionFactory ?? (_sessionFactory = InitializeSessionFactory ());
}
}
private ISessionFactory InitializeSessionFactory ()
{
return Fluently.Configure ()
.Database (PostgreSQLConfiguration.Standard.ConnectionString (_connectionString).
Dialect ("NHibernate.Dialect.PostgreSQL82Dialect"))
// Use class mappings
.Mappings (m => m.FluentMappings.AddFromAssembly (Assembly.GetExecutingAssembly ()))
// Will Update and create tables if does not exist
.ExposeConfiguration (cfg => new SchemaUpdate (cfg).Execute (true, true))
.BuildSessionFactory ();
}
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork (ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession ();
Session.FlushMode = FlushMode.Auto;
_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 Rollback ()
{
if (_transaction.IsActive) {
_transaction.Rollback ();
}
}
public void Dispose ()
{
if (Session.IsOpen) {
Session.Close ();
Session = null;
}
}
}
Repository
public class Repository<TEntity> : IReadWriteRepository<TEntity>
where TEntity : class
{
private readonly ISession _session;
public Repository (ISession session)
{
_session = session;
}
#region IWriteRepository
public bool Add (TEntity entity)
{
_session.Save (entity);
return true;
}
public bool Add (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Save (entity);
}
return true;
}
public bool Update (TEntity entity)
{
_session.Update (entity);
return true;
}
public bool Update (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Update (entity);
}
return true;
}
public bool Delete (TEntity entity)
{
_session.Delete (entity);
return true;
}
public bool Delete (System.Collections.Generic.IEnumerable<TEntity> entities)
{
foreach (TEntity entity in entities) {
_session.Delete (entity);
}
return true;
}
#endregion
#region IReadRepository
public System.Linq.IQueryable<TEntity> All ()
{
return _session.Query<TEntity> ();
}
public TEntity FindBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
{
return FilterBy (expression).SingleOrDefault ();
}
public TEntity FindBy (object id)
{
return _session.Get<TEntity> (id);
}
public System.Linq.IQueryable<TEntity> FilterBy (System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expression)
{
return All ().Where (expression).AsQueryable ();
}
#endregion
}
在 Intrastructure.DependencyInjectrion
我有:
public void RegisterServices (SimpleInjector.Container container)
{
var connectionSettings = ConfigurationManager.ConnectionStrings ["Connection"];
container.RegisterPerWebRequest<ISessionFactory> (() => {
NHibernateHelper objNHibernate = new NHibernateHelper (connectionSettings.ConnectionString);
return objNHibernate.SessionFactory;
});
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork> ();
container.RegisterPerWebRequest<ISession> (() => {
UnitOfWork unitOfWork = (UnitOfWork)container.GetInstance<IUnitOfWork> ();
return unitOfWork.Session;
});
container.RegisterOpenGeneric (typeof(IReadWriteRepository<>), typeof(Repository<>));
}
然后在我的服务中我会做这样的事情:
Web.UI.Services.CompanyService
public void CreateNewCompany (Company company)
{
if (_companyRepository.Add (company))
_unitOfWork.Commit ();
else
_unitOfWork.Rollback ();
}
在动态 Repository
中调用 _unitOfWork.Commit()
或 _unitOfWork.Rollback()
比在 Service
层中调用 _unitOfWork.Rollback()
更好吗?
我正在考虑通过将 IUnitOfWork
注入其中并添加一些额外的错误处理来改进通用 Repository
。
如果这不是一个好方法,有人可以给我一些改进的方向吗?注意:我确实想保留 repository pattern
,以防我们在几年后选择切换 ORM
。
在存储库中管理事务绝对不是标准方法,因为它消除了实现跨越多个存储库(或同一存储库上的多个操作)的业务逻辑的可能性,并且需要以原子方式执行。
我会尽量将事务管理保留在最顶层,这样才有意义,也就是说,如果您决定将应用程序托管在例如不同的环境。在您的情况下,这似乎是服务层;您还可以区分不同类型的服务,就像在领域驱动设计中所做的那样,其中 应用程序服务 和 领域服务 之间存在差异。 应用程序服务可能会编排多个域服务并处理事务管理和潜在的工作单元)。
希望对您有所帮助。