Вопрос

Я пытаюсь написать свой Модель предметной области, насколько это возможно, не учитывает постоянство.Единственное, что я сейчас делаю, это отмечаю каждое свойство и метод. virtual, поскольку NHibernate требует этого для отложенной загрузки.

В моем сборка модели предметной области Я определяю некоторые интерфейсы репозитория:

public interface IRepository<TEntity> where TEntity : EntityBase {
    TEntity Get(int id);
    /* ... */
}
public interface IProductRepository : IRepository<Product> { ... }

Тогда у меня есть сборка данных.Этот будет ссылаться на NHibernate, он знает о его существовании.Это сборка, реализующая эти интерфейсы репозитория:

public abstract class Repository<TEntity> : IRepository<TEntity> {
    public TEntity Get(ind id) { ... }
    /* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
    /* ... */
}

и так далее.

Теперь я хотел реализовать функциональность транзакций в мои репозитории.Для этого я бы добавил BeginTransaction метод в моем интерфейсе IRepository.Однако я не могу определить тип возвращаемого значения как NHibernate.ITransaction, поскольку я хочу, чтобы модель предметной области оставалась в неведении и не была вынуждена ссылаться на сборку NHibernate из сборки моей модели предметной области.

Что бы вы сделали?

Вы бы просто реализовали void BeginTransaction(), а void Commit(), и void RollBack() методы интерфейса, и пусть реализация репозитория управляет ITransaction объект внутри?

Или вы нашли бы способ разоблачить ITransaction объект позволить клиенту управлять транзакцией напрямую с ним, а не использовать методы репозитория?

Спасибо!

Это было полезно?

Решение

Вы можете взглянуть на Острая архитектура в котором уже реализовано все, о чем вы говорите, включая универсальные репозитории с поддержкой транзакций.Решение заключается в том, что IRepository имеет свойство DbContext, которое инкапсулирует транзакции (на самом деле это интерфейс).Это первый из описанных вами вариантов (пользовательский интерфейс транзакций, скрывающий NHibernate).И это работает хорошо.

Я думаю, вы даже можете повторно использовать код S#arp, независимо от того, собираетесь ли вы использовать полную структуру.

Другие советы

Транзакции IMO всегда должны начинаться и заканчиваться в бизнес-логике, другими словами, транзакция должна начинаться на уровне обслуживания, а не на уровне репозитория, и репозиторий должен включаться в транзакцию, в идеале это должно быть сделано неявно.

Теперь, если вы используете NH, то если ваш сервис и репозитории используют один и тот же «сеанс» (что и должно быть), вы можете вызвать «BeginTransaction» на уровне сервиса и выполнить фиксацию или откат по мере необходимости:

Например, представьте себе метод в сервисе:

  public void RegisterCustomer(Customer customer)
    {
        try
        {
            using(var transaction = _session.BeginTransaction())
            {
                _customerRepository.Save(customer);
                _customerSurveyRepository.Save(customerSurvey);
                // DO What ever else you want...
                transaction.Commit();
            }
        }
        catch (Exception exn)
        {
            throw new AMException(FAILED_REGISTRATION, exn);
        }
     }

То, как репозитории получают ссылку на один и тот же сеанс, можно решить путем внедрения конструкторов или использования SessionFactory для получения текущего сеанса...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top