I'm building a DDD application with CQRS.
In my aggregate I have a Budget
aggregate root and BudgetedTransaction
entity.
Budget
keeps track of the transactions, the list of BudgetedTransactions
is the property of the Budget
.
In the database that's a 1-to-many relationship between the Budget
and BudgetedTransaction
.
My Budget
class:
public class Budget : Entity, IAggregateRoot
{
private readonly List<BudgetedTransaction> _budgetedTransactions;
private Budget() { } //ef core
public Budget(List<BudgetedTransaction> budgetedTransactions)
{
_budgetedTransactions = budgetedTransactions;
}
}
I want to use CQRS and have separate repositories for reading and writing (Dapper for reading and EF for writing).
I'm struggling to understand how to retrieve and initialize the Budget
root for writing purposes. Suppose I want to add a functionality of adding a new transaction.
Below is my Handle method in the command handler. How do I get from the list of DTOs to the list of actual entities, while not using EF for reads?
I'm coming to a conclusion that it is not possible and the reads with Dapper serve a different purpose (fetching persisted data to return from the API only)
Which would mean that my write repositories should really be both read and write repos, using EF, for the purposes of reading entities to make changes to them. Is that right? Is there a better solution?
public async Task<Guid> Handle(AddBudgetedTransactionCommand command, CancellationToken cancellationToken)
{
var budgetWithTransactionsDto = await _budgetRepositoryRead.GetBudgetById(command.AddBudgetedTransactionRequest.BudgetId);
var transactions = budgetWithTransactionsDto.BudgetedTransactions.ToList();
var budget = new Budget(?);
var transaction = new BudgetedTransaction(command.AddBudgetedTransactionRequest.BudgetId,
command.AddBudgetedTransactionRequest.BudgetingCategoryId,
command.AddBudgetedTransactionRequest.TransactionType,
command.AddBudgetedTransactionRequest.TransactionOccurrences,
command.AddBudgetedTransactionRequest.StartDate,
command.AddBudgetedTransactionRequest.Amount);
budget.AddBudgetedTransaction(transaction);
await _budgetRepositoryWrite.UnitOfWork.SaveEntitiesAsync(cancellationToken);
budget.AddDomainEvent(new BudgetedTransactionAdded(transaction));
return transaction.Id;
}
Method added to Budget
:
public void AddBudgetedTransaction(BudgetedTransaction transaction)
{
_budgetedTransactions.Add(transaction);
}