插入嵌套对象 EF Core 5

Inserting Nested Objects EF Core 5

我有以下实体:

  1. 批量
  2. 示例
  3. 样本容器
  4. 样本测试

一个批次包含多个样本。一个样本包含许多 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);

这里只复制了批次对象,没有复制相关的样品和容器duplicated/inserted。

尝试 #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;
        }
 }

这次我一到达Detach函数就面临以下异常:

{"The property 'Batch.Id' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal."}

我就是这样做的,大部分都是不言自明的。

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;
        }

    }