首页 > 解决方案 > 复制实体时出现违规错误

问题描述

我有以下实体项目天气具有以下结构

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 一起使用。

任何人都可以让我知道这方面的任何想法,非常感谢。

标签: .netpostgresqlentity-framework-corenpgsql

解决方案


好的,我知道可能发生的事情。当您查询 时cloneOfSourceProject,您正在指定AsNoTracking(). 这意味着ProjectWeather附加到您正在查询的项目的对象也会返回,但 EF Core 不会跟踪其身份。然后您更改项目ProjectNumber并保存它,因此 EF Core 尝试保存整个对象及其ProjectWeatherProjectNumber未更改)。这导致 postgresProjectWeather用一个已经存在的键写入一个新行,因此是一个异常。

如果这是正确的,您应该能够通过在保存项目之前将ProjectWeather' 键设置为 new来解决问题:ProjectNumber

cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;

推荐阅读