我正在用CQRS构建一个DDD应用程序。在聚合中,我有一个Budget
聚合根和一个BudgetedTransaction
实体。Budget
跟踪交易,BudgetedTransactions
的列表是Budget
的属性。在数据库中,Budget
和BudgetedTransaction
之间是一对多的关系。
MyBudget
class:
public class Budget : Entity, IAggregateRoot
{
private readonly List<BudgetedTransaction> _budgetedTransactions;
private Budget() { } //ef core
public Budget(List<BudgetedTransaction> budgetedTransactions)
{
_budgetedTransactions = budgetedTransactions;
}
public void AddBudgetedTransaction(BudgetedTransaction transaction)
{
_budgetedTransactions.Add(transaction);
}
}
在我的命令处理程序中,我使用EF core来检索Budget
,以及在repo中使用Include
方法的事务
public async Task<BudgetedTransactionDto> Handle(AddBudgetedTransactionCommand command, CancellationToken cancellationToken)
{
var budget = await _budgetRepository.GetBudgetById(command.AddBudgetedTransactionRequest.BudgetId);
var transaction = new BudgetedTransaction(
_guidService.NewGuid,
command.AddBudgetedTransactionRequest.BudgetId,
command.AddBudgetedTransactionRequest.BudgetingCategoryId,
command.AddBudgetedTransactionRequest.TransactionType,
command.AddBudgetedTransactionRequest.TransactionOccurrences,
command.AddBudgetedTransactionRequest.StartDate,
command.AddBudgetedTransactionRequest.Amount,
_dateTimeService.UtcNow);
budget.AddBudgetedTransaction(transaction);
await _budgetRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
budget.AddDomainEvent(new BudgetedTransactionAdded(transaction));
return await _transactionsRepositoryRead.GetBudgetedTransactionById(transaction.Id);
}
BudgetRepository
:
internal class BudgetRepository : IBudgetRepository
{
private readonly BudgetingDbContext _dbContext;
public BudgetRepository(BudgetingDbContext dbContext)
{
_dbContext = dbContext;
}
public IUnitOfWork UnitOfWork => _dbContext;
public async Task<Budget> GetBudgetById(Guid budgetId)
{
return await _dbContext.Budgets
.Where("BudgetedTransactions")
.Include(b => b.)
.SingleAsync();
}
}
最后是实体配置。为了迁移的目的,我设法避免添加导航属性到Budget
。
public class BudgetedTransactionEntityTypeConfiguration : IEntityTypeConfiguration<BudgetedTransaction>
{
public void Configure(EntityTypeBuilder<BudgetedTransaction> builder)
{
builder
.ToTable("BudgetedTransaction")
.HasKey(t => t.Id);
builder
.Property<Guid>("Id")
.IsRequired();
builder.HasOne<Budget>()
.WithMany();
builder
.Property<Guid>("BudgetId")
.HasColumnType("uniqueidentifier")
.IsRequired();
}
}
然而,当从DB检索预算时,我得到异常:System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Query.InvalidIncludePathError': Unable to find navigation 'BudgetedTransactions' specified in string based include path 'BudgetedTransactions'. This exception can be suppressed or logged by passing event ID 'CoreEventId.InvalidIncludePathError' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
我理解这个问题,我提供了不存在的导航属性的名称。那么,是否有可能加载Budget
与Transactions
,而不是创建导航属性?
如果你想使用include
的导航属性,必须添加public
public Budget {
....
private readonly List<BudgetedTransaction> _budgetedTransactions;
public IEnumerable<BudgetedTransaction> BudgetedTransactions => _budgetedTransactions?.ToList()
....
}