该属性是键的一部分,因此无法修改或标记为已修改(ForeignKey 不是键)

mah*_*hdi 9 c# entity-framework entity-framework-core ef-core-6.0

我有两个没有键关系的实体,当我想编辑人员中的人员代码字段时,会向我显示此错误。 'The property 'Personnel.PersonnelCode' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal.' EnrolNumberPersonnelNum 表也没有与我的表中更改的人员记录有关系的记录

人员等级

public class Personnel : BaseEntity, IBaseEntityTypeConfiguration<Personnel>
    {
        public Personnel()
        {
            EnrolNumberPersonnelNums = new HashSet<EnrolNumberPersonnelNum>();
        }
        [Key]
        public int PersonnelId { get; set; }
        public string PersonnelCode { get; set; }
        public virtual ICollection<EnrolNumberPersonnelNum> EnrolNumberPersonnelNums { get; set; }

        public void Map(EntityTypeBuilder<Personnel> builder)
        {
            builder.ToTable("Personnel", "HR");

            builder.Property(e => e.PersonnelCode).HasMaxLength(50);
        }
    }
Run Code Online (Sandbox Code Playgroud)

EnrolNumberPersonnelNum 类

 public class EnrolNumberPersonnelNum : BaseEntity, IBaseEntityTypeConfiguration<EnrolNumberPersonnelNum>
    {
        public EnrolNumberPersonnelNum()
        {
        }
        [Key]
        public int EnrolNumberPersonnelNumId { get; set; }
        public string PersonnelCode { get; set; }
        public virtual Personnel Personnel { get; set; }
     
        public void Map(EntityTypeBuilder<EnrolNumberPersonnelNum> builder)
        {
            builder.ToTable("EnrolNumberPersonnelNum", "HR");

            builder.Property(e => e.PersonnelCode)
                .HasMaxLength(50);

            builder.HasOne(c => c.Personnel).WithMany(c => c.EnrolNumberPersonnelNums)
                .HasForeignKey(c => c.PersonnelCode).HasPrincipalKey(c => c.PersonnelCode)
                .OnDelete(DeleteBehavior.ClientNoAction)
                .HasConstraintName($"FK_{nameof(EnrolNumberPersonnelNum)}_{nameof(Personnel)}_{nameof(PersonnelCode)}");
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我想编辑人员实体中的人员代码并且 EnrolNumberPersonnelNum 表为空时出现错误消息。

Iva*_*oev 10

HasPrincipalKey(c => c.PersonnelCode)这里

builder.HasOne(c => c.Personnel).WithMany(c => c.EnrolNumberPersonnelNums)
    .HasForeignKey(c => c.PersonnelCode).HasPrincipalKey(c => c.PersonnelCode)
    .OnDelete(DeleteBehavior.ClientNoAction)
    .HasConstraintName($"FK_{nameof(EnrolNumberPersonnelNum)}_{nameof(Personnel)}_{nameof(PersonnelCode)}");
Run Code Online (Sandbox Code Playgroud)

PersonnelCode将实体的属性标记Personnel备用键

除了主键之外,备用键还充当每个实体实例的备用唯一标识符;它可以用作关系的目标。当使用关系数据库时,这映射到备用键列上的唯一索引/约束以及引用该列的一个或多个外键约束的概念。

在 EF Core 中,所有类型的密钥(主密钥和备用密钥)都是只读的,即 EF Core 不允许更新它们(是必需的,只能为新实体提供)。这基本上就是错误消息在开始时告诉您的内容

属性“Personnel.PersonnelCode”是键的一部分,因此无法修改或标记为已修改。

话虽这么说,如果您需要可编辑该属性,到目前为止还没有针对此类模型的解决方案。错误消息中的建议

要使用标识外键更改现有实体的主体,请首先删除依赖项并调用“SaveChanges”,然后将依赖项与新主体关联。

似乎不可行,因为显然您不能删除依赖项(EnrolNumberPersonnelNums在您的情况下),然后将它们与新的父项关联(因为它们被删除)。最终您可以尝试将它们加载到内存中,然后调用RemoveRange,修改父键,然后SaveChanges更新PersonnelCode缓存的子实例,调用,AddRange然后调用SaveChanges。看起来不可靠/容易出错,但值得尝试。

如果允许修改数据库,最好删除PersonnelCodefromEnrolNumberPersonnelNum并创建和使用int PersonnelId绑定到 PK 的常规 FK Personnel。这样您就可以删除备用键(如果需要,只需添加唯一约束),如文档中所述

提示

如果您只想强制列的唯一性,请定义唯一索引而不是备用键(请参阅索引)。在 EF 中,备用键是只读的,并在唯一索引上提供额外的语义,因为它们可以用作外键的目标。

这将允许像任何其他属性一样更新PersonnelCodeof 。Personel