Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8217217
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T12:23:21+00:00 2026-06-07T12:23:21+00:00

I have a payment system as shown below. The payment can be made through

  • 0

I have a payment system as shown below. The payment can be made through multiple gift coupons. The gift coupons are issued along with a purchase. The customer can make use of this gift coupon for future purchase.

When a Payment is made through gift coupon, the UsedForPaymentID column in GiftCoupon table need to be updated with that PaymentID (for the giftcoupon ID).

The GiftCouponIDs are already available in the database. When a customer produces a gift coupon, it has GiftCouponID printed on it. The operator need to enter this CouponID to the system to make the Payment.

For the MakePayment() operation, it necessitates two repositories.

  1. Gift Coupon Repository
  2. Payment Repository

CODE

//Use GiftCouponRepository to retrieve the corresponding GiftCoupon object.

This involves use of two repositories for one transaction. Is it a good practice? If not, how can we change the design to overcome this?

Reference: In DDD the Aggregate should represent the transactional boundary. A transaction that requires the involvement of more than one aggregate is often a sign that either the model should be refined, or the transactional requirements should be reviewed, or both. Is CQRS correct for my domain?

enter image description here

C# CODE

public RepositoryLayer.ILijosPaymentRepository repository { get; set; }

public void MakePayment(int giftCouponID)
{
    DBML_Project.Payment paymentEntity = new DBML_Project.Payment();
    paymentEntity.PaymentID = 1;

    DBML_Project.GiftCoupon giftCouponObj;

    //Use GiftCouponRepository to retrieve the corresponding GiftCoupon object.     

    paymentEntity.GiftCouponPayments = new System.Data.Linq.EntitySet<DBML_Project.GiftCoupon>();
    paymentEntity.GiftCouponPayments.Add(giftCouponObj);

    repository.InsertEntity(paymentEntity);
    repository.SubmitChanges();
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T12:23:23+00:00Added an answer on June 7, 2026 at 12:23 pm

    I think what you really meant to ask was regarding ‘Multiple Aggregates in one transaction‘. I don’t believe there is anything wrong with using multiple repositories to fetch data in a transaction. Often during a transaction an aggregate will need information from other aggregates in order to make a decision on whether to, or how to, change state. That’s fine. It is, however, the modifying of state on multiple aggregates within one transaction that is deemed undesirable, and I think this what your referenced quote was trying to imply.

    The reason this is undesirable is because of concurrency. As well as protecting the in-variants within it’s boundary, each aggregate should be protected from concurrent transactions. e.g. two users making a change to an aggregate at the same time.

    This protection is typically achieved by having a version/timestamp on the aggregates’ DB table. When the aggregate is saved, a comparison is made of the version being saved and the version currently stored in the db (which may now be different from when the transaction started). If they don’t match an exception is raised.

    It basically boils down to this: In a collaborative system (many users making many transactions), the more aggregates that are modified in a single transaction will result in an increase of concurrency exceptions.

    The exact same thing is true if your aggregate is too large & offers many state changing methods; multiple users can only modify the aggregate one at a time. By designing small aggregates that are modified in isolation in a transaction reduces concurrency collisions.

    Vaughn Vernon has done an excellent job explaining this in his 3 part article.

    However, this is just a guiding principle and there will be exceptions where more than one aggregate will need to be modified. The fact that you are considering whether the transaction/use case could be re-factored to only modify one aggregate is a good thing.

    Having thought about your example, I cannot think of a way of designing it to a single aggregate that fulfills the requirements of the transaction/use case. A payment needs to be created, and the coupon needs to be updated to indicate that it is no longer valid.

    But when really analysing the potential concurrency issues with this transaction, I don’t think there would ever actually be a collision on the gift coupon aggregate. They are only ever created (issued) then used for payment. There are no other state changing operations in between. Therefore in this instance we don’t need to be concerned about that fact we are modifying both the payment/order & gift coupon aggregate.

    Below is what I quickly came up with as a possible way of modelling it

    • I couldn’t see how payments make sense without an order aggregate that the payment(s) belong to, so I introduced one.
    • Orders are made up of payments. A payment can be made with gift coupons. You could create other types of payments, such as CashPayment or CreditCardPayment for example.
    • To make a gift coupon payment, the coupon aggregates must be passed to the order aggregate. This then marks the coupon as used.
    • At the end of the transaction, the order aggregate is saved with its new payment(s), and any gift coupon used is also saved.

    Code:

    public class PaymentApplicationService
    {
        public void PayForOrderWithGiftCoupons(PayForOrderWithGiftCouponsCommand command)
        {
            using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
            {
                Order order = _orderRepository.GetById(command.OrderId);
    
                List<GiftCoupon> coupons = new List<GiftCoupon>();
    
                foreach(Guid couponId in command.CouponIds)
                    coupons.Add(_giftCouponRepository.GetById(couponId));
    
                order.MakePaymentWithGiftCoupons(coupons);
    
                _orderRepository.Save(order);
    
                foreach(GiftCoupon coupon in coupons)
                    _giftCouponRepository.Save(coupon);
            }
        }
    }
    
    public class Order : IAggregateRoot
    {
        private readonly Guid _orderId;
        private readonly List<Payment> _payments = new List<Payment>();
    
        public Guid OrderId 
        {
            get { return _orderId;}
        }
    
        public void MakePaymentWithGiftCoupons(List<GiftCoupon> coupons)
        {
            foreach(GiftCoupon coupon in coupons)
            {
                if (!coupon.IsValid)
                    throw new Exception("Coupon is no longer valid");
    
                coupon.UseForPaymentOnOrder(this);
                _payments.Add(new GiftCouponPayment(Guid.NewGuid(), DateTime.Now, coupon));
            }
        }
    }
    
    public abstract class Payment : IEntity
    {
        private readonly Guid _paymentId;
        private readonly DateTime _paymentDate;
    
        public Guid PaymentId { get { return _paymentId; } }
    
        public DateTime PaymentDate { get { return _paymentDate; } }
    
        public abstract decimal Amount { get; }
    
        public Payment(Guid paymentId, DateTime paymentDate)
        {
            _paymentId = paymentId;
            _paymentDate = paymentDate;
        }
    }
    
    public class GiftCouponPayment : Payment
    {
        private readonly Guid _couponId;
        private readonly decimal _amount;
    
        public override decimal  Amount
        {
            get { return _amount; }
        }
    
        public GiftCouponPayment(Guid paymentId, DateTime paymentDate, GiftCoupon coupon)
            : base(paymentId, paymentDate)
        {
            if (!coupon.IsValid)
                throw new Exception("Coupon is no longer valid");
    
            _couponId = coupon.GiftCouponId;
            _amount = coupon.Value;
        }
    }
    
    public class GiftCoupon : IAggregateRoot
    {
        private Guid _giftCouponId;
        private decimal _value;
        private DateTime _issuedDate;
        private Guid _orderIdUsedFor;
        private DateTime _usedDate;
    
        public Guid GiftCouponId
        {
            get { return _giftCouponId; }
        }
    
        public decimal Value
        {
            get { return _value; }
        }
    
        public DateTime IssuedDate
        {
            get { return _issuedDate; }
        }
    
        public bool IsValid
        {
            get { return (_usedDate == default(DateTime)); }
        }
    
        public void UseForPaymentOnOrder(Order order)
        {
            _usedDate = DateTime.Now;
            _orderIdUsedFor = order.OrderId;
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a payment system as shown below. The payment can be made through
I have a recurring payment mode in the system. All is well, API successful
I have a payment_types table in which you can enter different payment types such
I am making a payment system for my site. Users can select one of
In my play1.2.4 app,I have a Customer who can have a Set of PaymentMethod
I have an AppEngine app. I'd like to add a payment system to it,
Im trying to create a payment system that integrates with eWay .. They have
We have a system like gift cards balance usage in the checkout page.While customers
I am new at paypal payment system... I have seen this been done, but
I have to implement classes that work with payment system (let's call it PaymentSystem)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.