复制实体时出现违规错误
getting a violation error while copying entities
我有以下实体项目天气具有以下结构
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
未更改)。这导致 postgres 使用已经存在的键写入新的 ProjectWeather
行,因此出现异常。
如果这是正确的,您只需在保存项目之前将 ProjectWeather
的密钥设置为新的 ProjectNumber
即可解决问题:
cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;
我有以下实体项目天气具有以下结构
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
未更改)。这导致 postgres 使用已经存在的键写入新的 ProjectWeather
行,因此出现异常。
如果这是正确的,您只需在保存项目之前将 ProjectWeather
的密钥设置为新的 ProjectNumber
即可解决问题:
cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;