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

问题描述 投票:1回答:1

我正在尝试在我的API中构建标签系统。我有一个带有“标签”的模型,如下所示:

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

而且Tag真的很简单(目前)

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之后。当我运行此代码时,出现此错误:

无法跟踪实体类型'ScreenshotTag'的实例,因为已经跟踪了另一个键值为'{ScreenshotId:1,TagId:th-1}'的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。

此错误发生在第一个_databaseContext.Remove(tag)上。有谁知道我该如何阻止这种情况的发生?

c# entity-framework ef-core-2.0
1个回答
1
投票
我不得不将方法更改为此:

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

© www.soinside.com 2019 - 2024. All rights reserved.