.net - 复制实体时出现违规错误
问题描述
我有以下实体项目天气具有以下结构
public class ProjectWeather
{
[Key, ForeignKey("Project")]
public string ProjectNumber { get; set; }
[GraphQLIgnore]
public virtual Project Project { get; set; }
[ForeignKey("WeatherStation")]
public string WeatherStationNumber { get; set; }
}
我有其他实体project
和结构如下所示
public class Project : PatchEntityProperties
{
[Key, GraphQLNonNullType]
public string ProjectNumber { get; set; }
public string Name { get; set; }
public bool IsLocked { get; set; }
public ProjectWeather Weather { get; set; } = new ();
}
我想要做的是使用下面的代码将一个项目信息复制到另一个
var cloneOfSourceProject = dbContext.Projects
.AsNoTracking()
.Where(a => a.ProjectNumber == sourceProjectNumber)
.SingleOrDefault();
// Tracked so we can remove existing project before adding copied entity
var targetProject = dbContext.Projects
.Where(a => a.ProjectNumber == targetProjectNumber)
.SingleOrDefault();
if (cloneOfSourceProject == default)
{
throw new ArgumentException($"The project with project number '{sourceProjectNumber}' does not exist; an invalid project cannot be copied.");
}
string targetProjectName;
if (targetProject == default)
{
targetProjectName = dbContext.Projects.AsNoTracking().Where(a => a.Number == targetProjectNumber).SingleOrDefault()?.Name ?? "";
}
else
{
targetProjectName = targetProject.Name;
dbContext.Remove(targetProject);
}
cloneOfSourceProject.ProjectNumber = targetProjectNumber;
cloneOfSourceProject.Name = targetProjectName;
dbContext.Add(cloneOfSourceProject);
dbContext.SaveChanges();
但是在重复键值上出现错误违反了对项目天气的 PK_projectweather 的唯一约束,我不确定如何克服该错误,上面的代码有什么问题。我正在将 EFcore 与 postgresql 一起使用。
任何人都可以让我知道这方面的任何想法,非常感谢。
解决方案
好的,我知道可能发生的事情。当您查询 时cloneOfSourceProject
,您正在指定AsNoTracking()
. 这意味着ProjectWeather
附加到您正在查询的项目的对象也会返回,但 EF Core 不会跟踪其身份。然后您更改项目ProjectNumber
并保存它,因此 EF Core 尝试保存整个对象及其ProjectWeather
(ProjectNumber
未更改)。这导致 postgresProjectWeather
用一个已经存在的键写入一个新行,因此是一个异常。
如果这是正确的,您应该能够通过在保存项目之前将ProjectWeather
' 键设置为 new来解决问题:ProjectNumber
cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;