我正在尝试在我的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; }
}
而一个标签是非常简单的(现在)
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)
。有谁知道我该如何阻止这种情况的发生?
我不得不将方法更改为此:
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);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句