Skip to content
Advertisement

EF Core 5 failing while trying to update a foreign key which is also part of a unique Index

Like the title says, I am trying to update a foreign key and getting below error:

The property ‘Student.APID’ 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.

The Student class looks like this:

 public partial class Student
{
    public Student()
    {
        EntityCodes = new HashSet<EntityCode>();
        StudentAPHists = new HashSet<StudentAPHist>();
    }

    public string DepartmentJurName { get; set; }
    public decimal StudentMBA { get; set; }
    public string Comments { get; set; }
    public bool Active { get; set; }
    public DateTime? dtLastVerified { get; set; }
    public string LastVerifiedBy { get; set; }
    public DateTime? dtCreated { get; set; }
    public string CreatedBy { get; set; }
    public DateTime? StudentVerificationExpiryDate { get; set; }
    public int APID { get; set; }
    public int? DTPID { get; set; }
    public int StudentID { get; set; }

    public virtual StudentPayee StudentPayee { get; set; }
    public virtual DelqStudentPayee DelqStudentPayee { get; set; }
    public virtual Department Department { get; set; }
    public virtual ICollection<EntityCode> EntityCodes { get; set; }
    public virtual ICollection<StudentAPHist> StudentAPHists { get; set; }
}

The StudentPayee looks like this:

public partial class StudentPayee
{
    public StudentPayee()
    {
        StudentPayeeUpdateHists = new HashSet<StudentPayeeUpdateHist>();
        Students = new HashSet<Student>();
    }

    public decimal StudentMBA { get; set; }
    public decimal PayeeCode { get; set; }
    public string TaxIDMask { get; set; }
    public bool? Active { get; set; }
    public int APID { get; set; }
    public decimal UserRecipient { get; set; }
    public decimal PmtRecipient { get; set; }
    public DateTime dtCreate { get; set; }
    public string CreatedBy { get; set; }
    public string LastUpdatedBy { get; set; }
    public virtual Student Student { get; set; }
    public virtual Payee Payee { get; set; }
    public virtual Recipient PmtRecipientNavigation { get; set; }
    public virtual Recipient UserRecipientNavigation { get; set; }
    public virtual ICollection<StudentPayeeUpdateHist> StudentPayeeUpdateHists { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

And the OnModelCreating method looks like this:

modelBuilder.Entity<Student>(entity =>
        {
            entity.ToTable("Student", "dbo");

            entity.HasIndex(e => new { e.APID, e.StudentMBA }, "UNQ_APID_StudentMBA")
                .IsUnique();

            entity.Property(e => e.Comments)
                .HasMaxLength(256)
                .IsUnicode(false);

            entity.Property(e => e.DepartmentJurName)
                .HasMaxLength(50)
                .IsUnicode(false);

            entity.Property(e => e.CreatedBy)
                .HasMaxLength(50)
                .IsUnicode(false);

            entity.Property(e => e.StudentMBA).HasColumnType("decimal(10, 0)");

            entity.Property(e => e.LastVerifiedBy)
                .HasMaxLength(50)
                .IsUnicode(false);               

            entity.Property(e => e.StudentVerificationExpiryDate).HasColumnType("datetime");

            entity.Property(e => e.dtCreated).HasColumnType("datetime");

            entity.Property(e => e.dtLastVerified).HasColumnType("datetime");

            entity.HasOne(d => d.StudentPayee)
                .WithMany(p => p.Students)
                .HasPrincipalKey(p => p.APID)
                .HasForeignKey(d => d.APID)
                .HasConstraintName("FK_APID_StudentPayee");

            entity.HasOne(d => d.DelqStudentPayee)
                .WithMany(p => p.Students)
                .HasForeignKey(d => d.DTPID)
                .OnDelete(DeleteBehavior.SetNull)
                .HasConstraintName("FK_Student_Delqpayee");

            entity.HasOne(d => d.Department)
                .WithMany(p => p.Students)
                .HasForeignKey(d => d.StudentMBA)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Student_Student");
        });

Entity config for StudentPayee:

 modelBuilder.Entity<StudentPayee>(entity =>
        {
            entity.HasKey(e => new { e.StudentMBA, e.PayeeCode })
                .HasName("PK_StudentIDMask");

            entity.ToTable("StudentPayee", "dbo");

            entity.HasIndex(e => new { e.PayeeCode, e.StudentMBA }, "NonClusteredIndex-20201218-155947")
                .IsUnique();

            entity.HasIndex(e => e.APID, "UNQ_APID")
                .IsUnique();

            entity.Property(e => e.StudentMBA).HasColumnType("decimal(10, 0)");

            entity.Property(e => e.PayeeCode).HasColumnType("decimal(10, 0)");

            entity.Property(e => e.APID).ValueGeneratedOnAdd();

            entity.Property(e => e.Active)
                .IsRequired()
                .HasDefaultValueSql("((1))");

            entity.Property(e => e.CreatedBy)
                .IsRequired()
                .HasMaxLength(50)
                .IsUnicode(false)
                .HasDefaultValueSql("(suser_sname())");

            entity.Property(e => e.LastUpdatedBy)
                .IsRequired()
                .HasMaxLength(50)
                .IsUnicode(false);

            entity.Property(e => e.PmtRecipient).HasColumnType("decimal(10, 0)");

            entity.Property(e => e.UserRecipient).HasColumnType("decimal(10, 0)");

            entity.Property(e => e.TaxIDMask)
                .HasMaxLength(200)
                .IsUnicode(false);

            entity.Property(e => e.dtCreate)
                .HasColumnType("datetime")
                .HasDefaultValueSql("(getdate())");

            entity.HasOne(d => d.Student)
                .WithMany(p => p.StudentPayees)
                .HasForeignKey(d => d.StudentMBA)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_StudentPayee_Student");

            entity.HasOne(d => d.Payee)
                .WithMany(p => p.StudentPayees)
                .HasForeignKey(d => d.PayeeCode)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_StudentPayee_Payee");

            entity.HasOne(d => d.PmtRecipientNavigation)
                .WithMany(p => p.StudentPayeePmtRecipientNavigations)
                .HasForeignKey(d => d.PmtRecipient)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_StudentPayee_PmtRecipient");

            entity.HasOne(d => d.UserRecipientNavigation)
                .WithMany(p => p.StudentPayeeTBRRecipientNavigations)
                .HasForeignKey(d => d.TBRRecipient)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_StudentPayee_TBRRecipient");
        });

As you can see the APID is a foreign key and part of the unique index. So, whenever I try to update the APID like below, I get the error. This used to work with Entity Framework 6.

Student _student = DataBase.Students
                           .Single(x => x.Student ID == studentId);

if (_student != null)
{
    _student.APID = p_APID;

    DataBase.SaveChanges();
}

Advertisement

Answer

I ended up using Context.Database.ExecuteSqlRaw(query) to update the foreign key instead of LINQ. Thanks for all your help.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement