无法跟踪,因为另一个具有相同键值的实例
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);
我正在尝试在我的 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);