не может быть отслежен, потому что другой экземпляр с таким же значением ключа - PullRequest
1 голос
/ 20 апреля 2020

Я пытаюсь создать систему тегов в моем 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 в одном go. Итак, я создал эту конечную точку:

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

Как видите, я вызываю SaveChangesAsyn c один раз. Это после того, как я удалил или добавил ScreenshotTags . Когда я запускаю этот код, я получаю эту ошибку:

Не удается отследить экземпляр типа сущности 'ScreenshotTag', поскольку другой экземпляр со значением ключа '{ScreenshotId: 1, TagId: th-1}' уже отслеживается. При присоединении существующих объектов убедитесь, что подключен только один экземпляр объекта с данным значением ключа.

Эта ошибка возникает в первом _databaseContext.Remove(tag). Кто-нибудь знает, как я могу предотвратить это?

1 Ответ

1 голос
/ 20 апреля 2020

Мне пришлось изменить свой метод следующим образом:

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