无法跟踪,因为另一个具有相同键值的实例

cannot be tracked because another instance with the same key value

我正在尝试在我的 API 中构建标签系统。 我有一个模型,它像这样附加了 "Tags":

public class Screenshot: UserExtension
{
    [Key] public int Id { get; set; }
    [Required, MaxLength(2083)] public string Url { get; set; }
    public int StartTime { get; set; }
    public int EndTime { get; set; }
    public State State { get; set; }

    public IList<ScreenshotTag> Tags { get; set; }
    public IEnumerable<ScreenshotVideo> Videos { get; set; }
}

ScreenshotTag 看起来像这样:

public class ScreenshotTag
{
    public int ScreenshotId { get; set; }
    public string TagId { get; set; }

    public Screenshot Screenshot { get; set; }
    public Tag Tag { get; set; }
}

标签非常简单(目前)

public class Tag
{
    [Key] public string Id { get; set; }

    public IEnumerable<ScreenshotTag> Tags { get; set; }
    public IEnumerable<VideoTag> Videos { get; set; }
}

问题是,我想一次性修改Screenshot标签。所以我创建了这个端点:

public async Task<bool> Handle(ScreenshotTagUpdate query, CancellationToken cancellationToken)
{
    var request = query.Model;
    var screenshot = await _mediator.Send(new ScreenshotGet(request.Id), cancellationToken);
    var model = screenshot.Create();

    foreach (var tag in model.Tags)
        if (!request.Tags.Any(m => m.Equals(tag.TagId)))
            _databaseContext.Remove(tag);

    foreach (var tag in request.Tags)
    {
        if (model.Tags.Any(m => m.TagId.Equals(tag))) continue;

        await _tagValidator.ValidateAsync(new Tag {Id = tag}, cancellationToken);
        _databaseContext.Add(new ScreenshotTag { ScreenshotId = request.Id, TagId = tag });
    }

    await _databaseContext.SaveChangesAsync(cancellationToken);

    return true;
}

如您所见,我只调用了一次 SaveChangesAsync。这是在我删除或添加 ScreenshotTags 之后。当我 运行 这段代码时,我得到这个错误:

The instance of entity type 'ScreenshotTag' cannot be tracked because another instance with the key value '{ScreenshotId: 1, TagId: th-1}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

此错误发生在第一个 _databaseContext.Remove(tag)。有谁知道我怎样才能阻止这种情况发生?

我不得不将我的方法更改为:

public async Task<bool> Handle(ScreenshotTagUpdate query, CancellationToken cancellationToken)
{
    var request = query.Model;
    var screenshot = await _mediator.Send(new ScreenshotGet(request.Id), cancellationToken);
    var model = screenshot.Create();

    foreach (var tag in model.Tags)
        if (!request.Tags.Any(m => m.Equals(tag.TagId)))
        {
            var t = _databaseContext.ScreenshotTags.Single(m =>
                m.TagId == tag.TagId & m.ScreenshotId == tag.ScreenshotId);
            _databaseContext.Remove(t);
        }

    foreach (var tag in request.Tags)
    {
        if (model.Tags.Any(m => m.TagId.Equals(tag))) continue;

        await _tagValidator.ValidateAsync(new Tag {Id = tag}, cancellationToken);
        _databaseContext.Add(new ScreenshotTag { ScreenshotId = request.Id, TagId = tag });
    }

    await _databaseContext.SaveChangesAsync(cancellationToken);

    return true;
}

我不喜欢这个解决方案,所以如果有人有更好的解决方案,请随时添加!

PS:我唯一改变的是:

_databaseContext.Remove(tag);

至:

var t = _databaseContext.ScreenshotTags.Single(m =>
    m.TagId == tag.TagId & m.ScreenshotId == tag.ScreenshotId);
_databaseContext.Remove(t);