Should I Pass a repository to a Domain Method that fires an Event

大兔子大兔子 提交于 2019-12-23 03:50:09

问题


slightly related to this question: Should I pass a repository to a domain object method that needs to fire an event after the methods actions have occurred and been persisted?

In this case the system needs to send emails of after the domain object's status is changed. Whilst unlikely, it could happen that the status change would not be persisted in which case the email should not be sent.

I could use a domain service to do the work, but all the logic of status changing belongs and is contained in the domain object so my services would end up looking like

 StatusService(Irepo repo) {

        void ChangeStatus(domainObject myObject, status newStatus) {
              try {
              myObject.ChangeStatus(newStatus);
              repo.Save(myObject);
              raiseEvent(new StausChangeEmailEvent(myObject))
              } catch { .. dont send email }
         }

Which id rather not do for several reason (one of which is there are now 2 ways of changing status only one of which sends the emails)

Id like to wrap it up in the Domain Method itself but this also doesn't feel right because I'm making the domain object responsible for its own persistence. (although I think I prefer it over the domain service way)

 class DomainObject() : IAggRoot {

 ...
 public ChangeStatus(irepo repo, status newStatus) {
    ..logic logic 
    this.Status = newStatus;
    repo.Save(this);
    raiseEvent(new StausChangeEmailEvent(myObject))
 }

 }

There's a bit of complications about the business logic, but really I'm interested how to fire events ONLY after the Domain Objects are persisted.

Edit: It is not so important if the email fails to send, it is important that an email is not sent if the status does not 'take' as senior people in the organisation people may receive invalid instructions in their mailbox..


回答1:


It would be nicer to have consistent transactional behavior. You could commit events in the same transaction (queue or db), and dispatch from there. Anyways, if this is not what you're looking for, you could also have your aggregate record the event instead of having it raise it directly. This allows you to first commit your database transaction, and then to dispatch the event.

public interface IRecordingAggRoot {
     IEnumerable<IEvent> RecordEvents();
}

_repository.Save(aggregate);
_tx.Commit();
_dispatcher.Dispatch(aggregate.RecordedEvents());


来源:https://stackoverflow.com/questions/22084699/should-i-pass-a-repository-to-a-domain-method-that-fires-an-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!