Open Closed

Question About EventBus and Triggering a Custom Event After Transaction is committed and Before Transaction is Committed #11250


0
cangunaydin created

Hello, I have a question about domain events. I want to create custom domain events. I have different purposes to create these domain events. Here are 2 seperate use cases.

I have an Entity who has status property, and when status is changed from the entity, i want to send an email to the user. Code Ex:

  public class Offer : FullAuditedEntity, IMustHaveTenant
    {
        //constructor and some code over here.
        public OfferStatus Status {get; private set;}
        public DateTime ApprovedDate{get;private set;}


        public void ApproveOffer(){
            Status=OfferStatus.Approved;
            ApprovedDate=Clock.Now
            //trigger a domain event.
            EventBus.Default.Trigger(new OfferStatusChangedEventData(Status, OfferStatus.CustomerApproved, this));
        }

    }

    public class OfferStatusChangedEventData:EventData
    {
        public OfferStatusChangedEventData(OfferStatus newValue, OfferStatus oldValue, Offer offer)
        {
            NewValue = newValue;
            OldValue = oldValue;
            Offer = offer;
        }

        public OfferStatus NewValue { get; private set; }

        public OfferStatus OldValue { get; private set; }

        public Offer Offer { get; private set; }

    }
    public class OfferStatusChangedEventHandler : IEventHandler<OfferStatusChangedEventData>, ITransientDependency
    {
        //handle it over here.
        //send an email

    }

I believe with this code even if the transaction fails, it is gonna send the email to the user (Let's assume ApproveOffer() method is called from application service ). So what i want is to send the email after the transaction is committed to database. Is there any easy way to do it with aspnetzero?

And sometimes (when I use eventual consistency) I want to do the stuff within the same transaction.

So the question is... is there anyway to say to the EventBus.Default.Trigger() method, do this after unit of work completes? or vice versa?

PS: I know that, I can write an extra code to the DbContext OnModelSaveChanges(), but as I understand (correct me if i am wrong) I need to hold a collection of Events needs to be triggered in that case. Can i access to IEntityChangeEventHelper from the entity and store my events in that dictionary so it can be dispatched after the SaveChanges()? https://github.com/aspnetboilerplate/aspnetboilerplate/blob/dev/src/Abp.EntityFrameworkCore/EntityFrameworkCore/AbpDbContext.cs#L45


3 Answer(s)
  • 0
    ismcagdas created
    Support Team

    Hi @cangunaydin

    For such cases, I think it is better to create a background job to send emails in the transaction. So, if transaction fails, the background job will not be created. Then, you can send the email in background job.

  • 0
    cangunaydin created

    Hello @ismcagdas, thanks for the reply, How can i create the background job from an entity? shouldn't I need to inject IBackgroundJobManager? Can you give me a code example if there is a way to do it inside the entity?

  • 0
    ismcagdas created
    Support Team

    Hi,

    You shouldn't do it inside an entity. You can either do it in the DomainEvent or you can do it in a DomainService class.