Фон
Насколько я понимаю, шаблон единиц работы (UoW) по существу обеспечивает семантику транзакций. Другими словами, учитывая, что область агрегатов сохраняется в репозиториях, класс UoW позволяет потребителям домена регистрировать вызовы методов репозитория в элементарной операции. Скажем, у нас есть:
interface IAggregate<TKey> {
TKey Id { get; }
}
interface IRepository<TEntity, in TKey> where TEntity : IAggregate<TKey> {
TEntity Get(TKey id);
void Save(TEntity entity);
void Remove(TEntity entity);
}
interface IUnitOfWork {
void RegisterSave<TEntity>(TEntity entity);
void RegisterRemove<TEntity>(TEntity entity);
void RegisterUnitOfWork(IUnitOfWork uow);
void Commit();
void Rollback();
}
Предположим, что реализации IRepository
используют реляционную базу данных, а реализация IUnitOfWork.Commit
просто устанавливает транзакцию с базой данных и продолжает вызывать Save
или Remove
в соответствующих экземплярах IRepository
для всех операции, которые были зарегистрированы. Я бы сказал, что я обрисовал в общих чертах стандартную прямую интерпретацию шаблонов Aggregate Root, Repository и UoW (NHibernate / EF и всей их раздутой славы).
В прошлом я интерпретировал концепцию корневых границ агрегатов как означающую, что ссылки из одного агрегата в другой должны быть объективизированы свойством Id целевого агрегата в исходном агрегате. Например:
class User : IAggregate<int> {
int Id { get; private set; }
}
class Blog : IAggregate<int> {
int Id { get; private set; }
int AuthorUserId { get; set; }
}
Вопрос
Учитывая вышеупомянутое разделение проблем и интерпретацию границ агрегата, как можно было бы обеспечить поддержку транзакций потребителям, которым необходимо создать агрегат и сохранить его сгенерированный в хранилище идентификатор в другом агрегате? Например. как я могу создать User
и Blog
транзакционно с Blog.UserId
, установленным на User.Id
?
Я придумала несколько ответов (помечена вики сообщества), но все равно выкладываю здесь свой вопрос, чтобы получить обратную связь и получить больше ответов.