Я хочу перенести свою Единицу работы в сторону от моей бизнес-логики.Единица работы в общем хранилище
В 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();
}
было бы лучше перевести _unitOfWork.Commit()
или _unitOfWork.Rollback()
в eneric Repository
, а не в слой Service
?
Я думал об улучшении общего Repository
, введя в него IUnitOfWork
, добавив также дополнительную обработку ошибок.
Если это нехороший подход, может ли кто-нибудь дать мне некоторое направление, чтобы улучшить это? Примечание. Я хочу сохранить repository pattern
в случае, если мы захотим переключить ORM
через несколько лет.
Этот вид имеет смысл. Не могли бы вы сказать, что способ выполнения единицы работы в настоящий момент хорош? и просто оставить это как есть? Я пойду прочитаю немного больше DDD, Думаю, я пропустил что-то haha –
Я бы сказал, что реализация Unit of Work выглядит в целом прекрасной для меня.Я полагаю, что экземпляр создается на единицу работы (независимо от того, что может быть, возможно, HTTP-запрос). Единственное, о чем вы могли бы подумать, заключается в том, хотите ли вы реализовать финализатор, который распределяет единицу работы, и хотите ли вы проверить активные транзакции в распоряжении (если есть активная транзакция, выполнить откат и зарегистрировать ошибку или что-то еще , это предотвратит открытые транзакции - не уверен, что 'Session.Close()' позаботится об этом уже). – PermaFrost
Кроме того, я лично использовал бы подразделение работы немного по-другому, я бы не откатил транзакцию, если бы мог быть уверен, что ничего не изменилось, как это сделано в приведенном вами служебном коде. Обязательства всегда дешевле, чем откаты на РСУБД. – PermaFrost