У меня проблемы либо с правильным моделированием моего домена, либо я что-то неправильно понимаю (весьма вероятно).
Предыстория домена. У нас есть коллекция Lines. Линии имеют направление и позволяют отслеживать, какое отверстие находится слева и справа от него. Таким образом, линии образуют «паутину».
Код: Выделить всё
// Model
public class Hole
{
public int Id { get; set; }
}
public class Line
{
public int Id { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public int? HoleLeft { get; set; }
public int? HoleRight { get; set; }
// Extra code to store events, apply events and keep track of uncommitted events.
}
- строка имела HoleLeft или HoleRight.
- HoleLeft/Right существует.
- Ни одна строка не пересекает другую строку
Код: Выделить всё
public class CreateLineCommandHandler
{
private readonly ILineRepository _lineRepo;
private readonly IHoleRepository _holeRepo;
public CreateLineCommandHandler(ILineRepository lineRepository, IHoleRepository holeRepository)
{
_lineRepo = lineRepository;
_holeRepo = holeRepository;
}
public void Handle(CreateLineCommand command)
{
Hole left = _holeRepo.GetById(command.HoleLeft);
Hole right = _holeRepo.GetById(command.HoleRight);
if (command.HoleLeft is null && command.HoleRight is null)
throw new Exception("Only left or right can be null, not both.");
if (command.HoleLeft == command.HoleRight)
throw new Exception("Left and right holes can not be the same.");
if (command.HoleLeft is not null && left is null)
throw new Exception("Unable to find left hole");
if (command.HoleRight is not null && right is null)
throw new Exception("Unable to find right hole");
// Now what I would like to do is something like this.
List lines = _lineRepo.GetLinesFromHoles([left.id, right.id]);
foreach (Line l in lines)
{
// check if crossing and if so throw exception.
}
Line line = new Line(command.Id,
command.Start,
command.End,
command.HoleLeft,
command.HoleRight);
_lineRepo.Save(line);
}
}
Команда GetLinesFromHoles кажется невозможной, если я не задействую модель чтения. В реляционной базе данных это будет простой оператор выбора. Возможно, это была слишком длинная преамбула, чтобы задаться вопросом, как мы можем выполнять бизнес-логику в обработчиках команд, которым требуются данные из других агрегатов или через «внешние ключи», когда мы работаем с хранилищем событий.
Я попробовал вышеуказанное решение и застрял в этой фундаментальной проблеме. Я поискал информацию о переполнении стека и безуспешно искал в Google эту проблему.
Подробнее здесь: https://stackoverflow.com/questions/784 ... d-handlers