使用 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
}
}
这是我尝试过的方法(无济于事):
- 使用 Fluent API 为
Results
配置一对多关系(使用 .HasMany()
)。
modelBuilder.Entity<SingleSimulation>()
.HasMany(x => x.Results)
.WithOne();
- 使用
AddRange()
将结果对象添加到数据库,然后再将它们添加到父级并最终保存到数据库 (SaveChangesAsync
)。
- 使用
Attach()
在将结果对象添加到父级之前开始跟踪结果对象。
- 在添加子项并尝试保存它们之前从数据库加载父对象时使用
Include()
。
感觉好像遗漏了一些小东西,但在搜索文档和其他资源后我找不到问题所在。在创建父项以实际保存到数据库后,我需要做什么才能将子项添加到父项?
通过打印 EF Core 更改跟踪器的 LongView
进行调试后,我注意到在对象上未检测到任何更改(即使更改一个简单的字符串 属性)。事实证明,问题是我正在修改的 singleSim
对象是从与 scopedRepository
.
使用的对象不同的 dbContext
返回的
毕竟模型设置不是问题。即使没有 Fluent API 配置,设置也会按预期工作(即使使用只读集合和私有支持字段)。
我有 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
}
}
这是我尝试过的方法(无济于事):
- 使用 Fluent API 为
Results
配置一对多关系(使用.HasMany()
)。
modelBuilder.Entity<SingleSimulation>()
.HasMany(x => x.Results)
.WithOne();
- 使用
AddRange()
将结果对象添加到数据库,然后再将它们添加到父级并最终保存到数据库 (SaveChangesAsync
)。 - 使用
Attach()
在将结果对象添加到父级之前开始跟踪结果对象。 - 在添加子项并尝试保存它们之前从数据库加载父对象时使用
Include()
。
感觉好像遗漏了一些小东西,但在搜索文档和其他资源后我找不到问题所在。在创建父项以实际保存到数据库后,我需要做什么才能将子项添加到父项?
通过打印 EF Core 更改跟踪器的 LongView
进行调试后,我注意到在对象上未检测到任何更改(即使更改一个简单的字符串 属性)。事实证明,问题是我正在修改的 singleSim
对象是从与 scopedRepository
.
dbContext
返回的
毕竟模型设置不是问题。即使没有 Fluent API 配置,设置也会按预期工作(即使使用只读集合和私有支持字段)。