【问题标题】:getting a violation error while copying entities复制实体时出现违规错误
【发布时间】:2021-06-22 21:43:28
【问题描述】:

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

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。

谁能告诉我这方面的任何想法,非常感谢。

【问题讨论】:

  • 您正在创建与源项目具有相同 ID 的“cloneOfSourceProject”,而不删除源项目。删除源项目、更改 ID 或将克隆创建为新对象,然后简单地将源项目中的字段复制到其中。
  • 抱歉措辞,没有源代码的克隆,我实际上只使用 sourceProjectNumber 获取源项目
  • 你是对的,对不起,我错过了 ProjectNumber 是 ID 并且你正在更改它的事实。也许尝试创建一个新对象而不是保存作为查询结果的对象?
  • 您应该在帖子中添加原始错误消息。只是好奇,你为什么要在if (targetProject == default) 中第二次查询目标项目?
  • @atiyar 原消息是这个duplicate key value violates unique constraint on PK_projectweather on project weather

标签: .net postgresql entity-framework-core npgsql


【解决方案1】:

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

如果正确,您应该可以通过在保存项目之前将ProjectWeather 的密钥设置为新的ProjectNumber 来解决问题:

cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;

【讨论】:

  • 是的,这是正确的,但你是什么意思从项目天气中删除实体
  • 在我的回答中添加了一行代码来解释我的意思
  • 抱歉还是出现同样的错误,我在保存实体之前放了这一行,比如cloneOfSourceProject.ProjectNumber = targetProjectNumber; cloneOfSourceProject.Name = targetProjectName; cloneOfSourceProject.Weather.ProjectNumber = targetProjectNumber;
  • 或者我是否需要在项目天气中删除现有项目编号,并在插入新项目时自动完成
  • 射击。你能确认它抱怨的重复键实际上是sourceProjectNumber吗?
猜你喜欢
  • 2012-10-10
  • 2021-02-13
  • 2019-07-05
  • 1970-01-01
  • 2021-05-18
  • 2021-07-04
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
相关资源
最近更新 更多