Я недавно начал новый проект с использованием архитектуры DDD. У меня есть 2 отдельные базы данных для одного и того же ограниченного контекста. Я знаю, что разные ограниченные контексты общаются друг с другом через очереди сообщений. Но поскольку у меня есть функции запросов и команд в одном и том же ограниченном контексте, я не знаю, как синхронизировать и модель чтения, и модель записи (в одном и том же ограниченном контексте).
Я использовал NH для записи (Command) и EF для чтения (Query). Я использовал Unit Of Work для NH, украсил все свои команды Unit Of Work и сделал их транзакционными для агрегата:
public class NhUnitOfWork : IUnitOfWork
{
private readonly ISession _session;
public NhUnitOfWork(ISession session)
{
_session = session;
}
public void Begin()
{
_session.Transaction.Begin(IsolationLevel.ReadCommitted);
}
public void Commit()
{
_session.Transaction.Commit();
}
public void Rollback()
{
_session.Transaction.Rollback();
}
}
и декоратор транзакций:
public class TransactionalCommandHandlerDecorator<T>:ICommandHandler<T>
{
private ICommandHandler<T> _commandHandler;
private IUnitOfWork _unitOfWork;
public TransactionalCommandHandlerDecorator(ICommandHandler<T> commandHandler, IUnitOfWork unitOfWork)
{
_commandHandler = commandHandler;
_unitOfWork = unitOfWork;
}
public void Handle(T command)
{
_unitOfWork.Begin();
try
{
_commandHandler.Handle(command);
_unitOfWork.Commit();
}
catch (Exception exp)
{
_unitOfWork.Rollback();
throw;
}
}
}
Итак, на прикладном уровне, в команде создания я должен организовать бизнес-поток:
public class CategoryCommandHandlers:ICommandHandler<CreateCategoryCommand>
{
private readonly ICategoryRepository _repository;
private readonly ICategoryQueryService _queryService;
public CategoryCommandHandlers(ICategoryRepository repository, ICategoryQueryService queryService)
{
_repository = repository;
_queryService = queryService;
}
public void Handle(CreateCategoryCommand command)
{
var categoryId = new CategoryId(Guid.NewGuid());
var parentId=new CategoryId(command.ParentId);
var category=new Category(categoryId,command.Name,parentId);
var parent = _repository.GetById(parentId);
if (parent==null)
throw new ParentCategoryNotFoundException();
_repository.Create(category);
var queryModel = new CategoryQuery(categoryId.Value, category.Name, parentId.Value);
_queryService.Create(queryModel);
}
}
Но я не знаю, в чем проблема. все работает без единой ошибки, но я прочитал модель, сохраненную в базе данных Query, и записал модель, отправленную.
Если у меня должен быть отдельный транзакционный декоратор для модели чтения, как я могу быть уверен в правильном выполнении обеих транзакций без ошибок? или откат, если кто-то обнаружил ошибку?
Или, может быть, команда совершенно неверна, и я не знаю, как обрабатывать и синхронизировать чтение и запись!