在EF Core中保存实体时识别循环依赖

时间:2018-10-02 17:02:55

标签: c# sql-server entity-framework-core

我有一个名为Record的表,每个Record都有一个名为RecordImage的图像文件的集合。 RecordImage表中有一个IsMainImage标志,用于指示Record的哪些图像是主图像。每个IsMainImage只能有一个Record

public class Record
{
    public Guid RecordId { get; set; }
    public ICollection<RecordImage> RecordImage { get; set; }
}

public class RecordImage
{
    public Guid RecordImageId { get; set; }
    public Guid RecordId { get; set; }
    public byte[] ImageData { get; set; }
    public bool IsMainImage { get; set; }

    public virtual Record Record { get; set; }
}

我正在使用ajax文件上传器来更新RecordImages,用户点击了一个复选框以勾选主图像,并且相关的RecordImage在服务器上已更新。执行此操作时,我必须检查现有的IsMainImage并将其设置为false以支持新的{}:

[HttpPut]
public async Task<IActionResult> Put(Guid key, string values)
{
RecordImage image = await _context.RecordImage.FindAsync(key);

if (image == null)
{
    return NotFound();
}

JsonConvert.PopulateObject(values, image);

if (TryValidateModel(image))
{
    if (image.IsMainImage)
    {
        // Check if a different Image is already flagged as the Record's MainImage.
        RecordImage oldMainImage = await _context.RecordImage
            .SingleOrDefaultAsync(a => a.RecordId == image.RecordId && a.IsMainImage && a.RecordImageId != image.RecordImageId);

        // Clear old MainImage.
        if (oldMainImage != null)
        {
            oldMainImage.IsMainImage = false;
        }
    }

    await _context.SaveChangesAsync();

    return Ok(); 
}

return BadRequest(ModelState);
}

但是,此操作失败,但出现以下异常:

  

由于在中检测到循环依赖性,因此无法保存更改   要保存的数据

通过分离正在更新的映像并将更改保存到旧的MainImage,然后重新附加映像,我可以解决此问题:

[HttpPut]
public async Task<IActionResult> Put(Guid key, string values)
{
RecordImage image = await _context.RecordImage.FindAsync(key);

if (image == null)
{
    return NotFound();
}

JsonConvert.PopulateObject(values, image);

if (TryValidateModel(image))
{
    // Use a Transaction as we need to call SaveChanges() more than once in this operation.
    using (var transaction = await _context.Database.BeginTransactionAsync())
    {
        // Image being updated needs to be detached before modifying and saving other entities.
        _context.Entry(image).State = EntityState.Detached;

        if (image.IsMainImage)
        {
            // Check if a different Image is already flagged as the Record's MainImage.
            RecordImage oldMainImage = await _context.RecordImage
                .SingleOrDefaultAsync(a => a.RecordId == image.Record && a.IsMainImage && a.RecordImageId != image.RecordImageId);

            // Clear old MainImage.
            if (oldMainImage != null)
            {
                oldMainImage.IsMainImage = false;
            }
        }

        // Save changes to other Images before reattaching and saving changes to the Image
        // being updated.
        await _context.SaveChangesAsync();

        _context.Entry(image).State = EntityState.Modified;
        await _context.SaveChangesAsync();

        transaction.Commit();

        return Ok(); 
    }
}

return BadRequest(ModelState);
}

这可以使我得到所需的东西,但是我不完全舒服,因为我不明白为什么。以前,我似乎所做的只是在上下文中更新多个RecordImage,将一个IsMainImage设置为true,另一个IsMainImage设置为false。我没有尝试更新任何父母或孩子,因为在上下文中我什至没有Including()。这种循环依赖的根源可能是什么?

0 个答案:

没有答案