使用 EF Core 6 创建后添加时不保存相关数据

Related data not saved when added after creation with EF Core 6

我有 POCO 对象,这些对象通过使用 EF Core 6 访问数据库的存储库公开。我可以将“父”对象保存到数据库中,并且在创建之前添加到父对象的相关数据也成功保存。但是,在创建父对象(SingleSimulation 个对象)后尝试将子对象(SingleSimulationResult 个对象)添加到父对象(SingleSimulation 个对象)时,子对象不会持久保存到数据库中。

下面是尝试向父对象添加和保存子对象的代码。

singleSim.AddResultsToSimulation(allResults);
Console.WriteLine($"# results: {singleSim.Results.Count}"); // # results: 2
await scopedRepository.Save();

var test = await scopedRepository.GetById(singleSim.Id);
Console.WriteLine($"# results test: {test.Results.Count}"); // # results: 0

SingleSimulationclass(BaseEntity只是定义了一个Id属性):

public class SingleSimulation : BaseEntity, IAggregateRoot
{
    public string Name { get; private set; }
    public string Description { get; private set; }

    public double Capital { get; private set; }

    public List<List<double>> Returns { get; private set; }

    private readonly List<SingleSimulationStrategy> _strategies = new List<SingleSimulationStrategy>();
    public IReadOnlyCollection<SingleSimulationStrategy> Strategies => _strategies.AsReadOnly();

    private List<SingleSimulationResult> _results = new List<SingleSimulationResult>();
    public IReadOnlyCollection<SingleSimulationResult> Results => _results.AsReadOnly();

    public SingleSimulation()
    {

    }

    public SingleSimulation(string name, string description, double capital, List<List<double>> returns, List<SingleSimulationStrategy> strategies)
    {
        Name = name;
        Description = description;
        Capital = capital;
        Returns = returns;
        _strategies = strategies;
    }

    public void AddResultsToSimulation(List<SingleSimulationResult> results)
    {
        if (_results is null)
            return;

        foreach (var result in results)
        {
            _results.Add(result);
        }
    }
}

存储库class:

public class SingleSimulationRepository : ISingleSimulationRepository
{
    private SimulationDbContext _dbContext;
    public SingleSimulationRepository(SimulationDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task Add(SingleSimulation entity)
    {
        await _dbContext.AddAsync(entity);
    }

    public async Task<SingleSimulation> GetById(int id)
    {
        return await _dbContext.SingleSimulations.FindAsync(id);
    }


    ...

    public async Task Save()
    {
        await _dbContext.SaveChangesAsync();
    }
}

数据库上下文:

public class SimulationDbContext : DbContext
{
    public SimulationDbContext(DbContextOptions<SimulationDbContext> options)
        : base(options)
    {
    }

    public DbSet<SingleSimulation> SingleSimulations { get; set; }
    public DbSet<SingleSimulationResult> SingleSimulationResults { get; set; }
    public DbSet<SingleSimulationStrategy> SingleSimulationStrategies { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Seed data and custom conversion functions
    }
}

这是我尝试过的方法(无济于事):

  1. 使用 Fluent API 为 Results 配置一对多关系(使用 .HasMany())。

modelBuilder.Entity<SingleSimulation>()
    .HasMany(x => x.Results)
    .WithOne();
  1. 使用 AddRange() 将结果对象添加到数据库,然后再将它们添加到父级并最终保存到数据库 (SaveChangesAsync)。
  2. 使用 Attach() 在将结果对象添加到父级之前开始跟踪结果对象。
  3. 在添加子项并尝试保存它们之前从数据库加载父对象时使用 Include()

感觉好像遗漏了一些小东西,但在搜索文档和其他资源后我找不到问题所在。在创建父项以实际保存到数据库后,我需要做什么才能将子项添加到父项?

通过打印 EF Core 更改跟踪器的 LongView 进行调试后,我注意到在对象上未检测到任何更改(即使更改一个简单的字符串 属性)。事实证明,问题是我正在修改的 singleSim 对象是从与 scopedRepository.

使用的对象不同的 dbContext 返回的

毕竟模型设置不是问题。即使没有 Fluent API 配置,设置也会按预期工作(即使使用只读集合和私有支持字段)。