title: Calling two different Aggregates from inside a Single CQRS Command
body: <p>I am working on a Online Support Ticketing System. In this system, different customers can register and post tickets (Each ticket will be linked to a customer). For the simplicity of my question I am going to keep only 2 Aggregates in the System, CustomerAggregate and TicketAggregate. My Domain model for those 2 Aggregates look as follows</p>
  <p><strong>/Domain/Entities/CustomerAggregate/Customer.cs</strong></p>
  <pre><code>namespace MyApp.Domain.Entities.CustomerAggregate
  {
      public class Customer : Entity, IAggregateRoot
      {
          public Customer(string name, int typeId)
          {
              Name = name;
              TypeId = typeId;
          }
  
          public string Name { get; private set; }
  
          public int TypeId { get; private set; }
  
          public CustomerType Type { get; private set; }
      }
  }
  </code></pre>
  <p><strong>/Domain/Entities/CustomerAggregate/CustomerType.cs</strong></p>
  <pre><code>namespace MyApp.Domain.Entities.CustomerAggregate
  {
      public class CustomerType : Enumeration
      {
          public static CustomerType Standard = new(1, nameof(Standard));
          public static CustomerType Premium = new(2, nameof(Premium));
  
          public CustomerType(int id, string name) : base(id, name)
          {
          }
  
  
          public static IEnumerable&lt;CustomerType&gt; List() =&gt;
              new[] { Standard, Premium };
  
          public static CustomerType FromName(string name)
          {
              var state = List()
                  .SingleOrDefault(s =&gt; string.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase));
  
              if (state == null)
              {
                  throw new MyAppDomainException($&quot;Possible values for CustomerType: {string.Join(&quot;,&quot;, List().Select(s =&gt; s.Name))}&quot;);
              }
  
              return state;
          }
  
          public static CustomerType From(int id)
          {
              var state = List().SingleOrDefault(s =&gt; s.Id == id);
  
              if (state == null)
              {
                  throw new MyAppDomainException($&quot;Possible values for CustomerType: {string.Join(&quot;,&quot;, List().Select(s =&gt; s.Name))}&quot;);
              }
  
              return state;
          }
  
      }
  }
  </code></pre>
  <p><strong>/Domain/Entities/TicketAggregate/Ticket.cs</strong></p>
  <pre><code>namespace MyApp.Domain.Entities.Ticket
  {
      public class Ticket : Entity, IAggregateRoot
      {
          public Ticket(int customerId, string description)
          {
              CustomerId = customerId;
              Description = description;
          }
  
          public int CustomerId { get; private set; }
  
          public string Description { get; private set; }
      }
  }
  </code></pre>
  <p>Inside my Application layer, I have different use cases. For example, I have CreateTicketCommand that basically creates the support ticket. My code looks as follows</p>
  <p><strong>/Application/UseCases/Tickets/CreateTicketCommand.cs</strong></p>
  <pre><code>namespace ConsoleApp1.Application.UseCases.Tickets.CreateTicket
  {
      public class CreateTicketCommand  : IRequest&lt;int&gt;
      {
          public int CustomerId { get; set; }
          public string Description { get; set; }
      }
  }
  </code></pre>
  <p><strong>/Application/UseCases/Tickets/CreateTicketCommandHandler.cs</strong></p>
  <pre><code>namespace MyApp.Application.UseCases.Tickets.CreateTicket
  {
      public class CreateTicketCommandHandler : IRequestHandler&lt;CreateTicketCommand, int&gt;
      {
          private readonly IApplicationDbContext _context;
  
          public CreateTicketCommandHandler(IApplicationDbContext context)
          {
              _context = context;
          }
  
          public async Task&lt;int&gt; Handle(CreateTicketCommand command, CancellationToken cancellationToken)
          {
              // Is it OK to fetch Customer Entity (that belongs to different aggregate) inside a Command Handler thats basically is dealing 
              // with another agreegate (Ticket)
              var customer = await _context.Customers.SingleOrDefaultAsync(c =&gt; c.Id = command.CustomerId);
  
              if (customer == null)
              {
                  throw new NotFoundException(nameof(Customer), command.CustomerId);
              }
  
              if (customer.CustomerType == CustomerType.Premium)
              {
                  var ticket = new Ticket(command.CustomerId, command.Description);
  
                  await _context.Tickets.AddAsync(ticket, cancellationToken);
  
                  await _context.SaveChangesAsync(cancellationToken);
  
                  return ticket.Id;
              }
              else
              {
                  throw new InvalidOperationException();
              }
          }
      }
  }
  </code></pre>
  <p>Now one of our Business requirement is that only Premium Customer can create a Ticket. If you notice that inside CreateTicketCommandHandler, I am first fetching the Customer and only creating the Ticket if the requested CustomerType is Premium.</p>
  <p>My question here is, is it good practice to interact with multiple Aggreegates from a single Command/Service (in this example Customer and Ticket), or should I be doing this logic to check CustomerType somewhere else?</p>
  <p><strong>Updated:</strong></p>
  <p>One of the alternate solution I was thinking was to create a DomainService for CustomerType.</p>
  <p><strong>/Application/UseCases/Customers/DomainServices/CustomerTypeService.cs</strong></p>
  <pre><code>    public class CustomerTypeService : ICustomerTypeService
      {
      
            private IApplicationDbContext _context;
      public CustomerTypeService(IApplicationDbContext context)
      {
            _context = context;
      }
      
      public CustomerType GetType(int customerId)
      {
            var customer = _context.Customer.SingleOrDefaultAsync(c =&gt; c.Id = customerId);
      
            return customer.Type;
      }
  }
  </code></pre>
  <p>The interface ICustomerTypeService will exist inside Ticket Domain Model.</p>
  <p><strong>/Domain/Entities/TicketAggregate/ICustomerTypeService.cs</strong></p>
  <p>And then inject ICustomerTypeService inside Ticket entity.</p>
  <pre><code>public Ticket(int customerId, string description, ICustomerTypeService service)
  {
  
      var customerType = service.GetType(customerId);
      //Check if customerType is valid to perform this operation, else throw exception
      CustomerId = customerId;
      Description = description;
  }
  </code></pre>
  <p>So in this usecase, putting that customertype logic inside command handler is right approach? or Domain service is right approach? or is there any other way this usecase should be handled?</p>