插入嵌套对象 EF Core 5
Posted
技术标签:
【中文标题】插入嵌套对象 EF Core 5【英文标题】:Inserting Nested Objects EF Core 5 【发布时间】:2021-10-19 03:25:41 【问题描述】:我有以下实体:
-
批次
样品
样品容器
样本测试
一个批次包含许多样本。一个样本包含许多SampleContainers
和许多SampleTests
。
我正在尝试复制批处理并插入数据库。
尝试 #1:在存储库中获取函数:
return await context.Set<TEntity>().FindAsync(id);
控制器:
var coc = await repository.Get(batchId);
coc.BatchStatusId = (int)Enums.BatchStatus.InProgress;
coc.IsTemplate = false;
coc.Id = 0;
var b = await repository.Add(coc);
这里只复制了批次对象,但没有复制/插入相关的样本和容器。
尝试 #2:我将 Get
函数更改如下:
public async override Task<Batch> Get(int id)
return await context.Set<Batch>()
.Include(p => p.Samples)
.FirstOrDefaultAsync(p => p.Id == id);
这一次批次被复制了,但是样本、容器和测试都用新的 batchId/FK 更新(我希望它们都被复制)。
尝试#3:按照this,我实现如下:
public async Task<int> DuplicateBatch([FromBody]int batchId)
try
var coc = await repository.Get(batchId);
coc.BatchStatusId = (int)Enums.BatchStatus.InProgress;
coc.IsTemplate = false;
coc.Id = 0;
var samples = coc.Samples.ToList();
repository.DetachEntity(coc);
var b = await repository.Add(coc);
var allSampleTests = await sampleTestRepo.GetAll();
var allSampleContainers = await sampleContainersRepo.GetAll();
var sampletests = from st in allSampleTests
join s in samples on st.SampleId equals s.Id
select st;
var sampleContainers = from sc in allSampleContainers
join s in samples on sc.SampleId equals s.Id
select sc;
sampleRepo.DetachEntities(samples);
sampleTestRepo.DetachEntities(sampletests.ToList());
sampleContainersRepo.DetachEntities(sampleContainers.ToList());
foreach (var s in samples)
s.BatchId = b.Id;
var sample = await sampleRepo.Add(s);
foreach (var st in sampletests)
st.SampleId = sample.Id;
await sampleTestRepo.Add(st);
foreach(var sc in sampleContainers)
sc.SampleId = sample.Id;
await sampleContainersRepo.Add(sc);
return 1;
catch (Exception ex)
return 0;
这一次我一达到分离功能就面临以下异常:
"属性 'Batch.Id' 是键的一部分,因此无法修改 或标记为已修改。更改现有实体的委托人 使用标识外键,首先删除依赖项并调用 'SaveChanges',然后将依赖项与新的关联 校长。”
【问题讨论】:
【参考方案1】:这就是我做的,大部分是不言自明的。
public async Task<int> DuplicateBatch([FromBody]int batchId)
try
//STEP 1: Fetch the entities
var coc2 = await repository.Get(batchId);
var samples = coc2.Samples.ToList();
var allSampleTests = await sampleTestRepo.GetAll();
var allSampleContainers = await sampleContainersRepo.GetAll();
var sampletests = samples.SelectMany(st => st.SampleTests).ToList();
var samplecontainers = samples.SelectMany(st => st.SampleContainers).ToList();
//STEP 2: Detach
var coc = repository.DetachEntity(coc2);
var samplesDetached = sampleRepo.DetachEntities(samples);
var sampleTestsDetached = sampleTestRepo.DetachEntities(sampletests);
var sampleContianersDetached = sampleContainersRepo.DetachEntities(samplecontainers);
//STEP 3: Update object
coc2.BatchStatusId = (int)Enums.BatchStatus.InProgress;
coc2.IsTemplate = false;
var b = await repository.Add(coc);
return 1;
catch (Exception ex)
return 0;
【讨论】:
以上是关于插入嵌套对象 EF Core 5的主要内容,如果未能解决你的问题,请参考以下文章
EF Core (< 5.0) HasComputedColumnSql - 在插入/更新或 SQL Server/AzureSQL 上的每个查询上计算?