cjkeilig
cjkeilig

Reputation: 101

EF Core - Self referencing relationship with custom foreign/principal key not mapped properties

I am trying to implement a self-referencing relationship in EF Core. I am trying to use a custom foreign key and principal key that are not mapped to a real database columns.

With the below code, I get the error

'No backing field could be found for property 'HeadOfHouseholdForeignKey' of entity type 'Person' and the property does not have a setter

Is there a way to have these foreign/principal keys which aren't mapped to a column in the DB? Is there a way to do it nicely in EF Core?

Example:

PersonContext.cs

using Microsoft.EntityFrameworkCore;

namespace ConsoleApp1
{
    public class PersonContext : DbContext
    {
        DbSet<Person> People;
        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Person>()
                .HasOne(p => p.HeadOfHouseHold)
                .WithMany()
                .HasForeignKey(p => p.HeadOfHouseholdForeignKey)
                .HasPrincipalKey(p => p.HeadOfHouseholdPrincipalKey);
        }
    }
}

Person.cs

namespace ConsoleApp1
{
    internal class Person
    {
        public int PersonId { get; set; }
        public string Name { get; set; }

        public string FamilyName { get; set; }

        public string PersonSequenceNumber { get; set; }

        public Person HeadOfHouseHold { get; set; }

        public string HeadOfHouseholdForeignKey
        {
            get
            {
                // Head of household always has '01' as PersonSequenceNumber in DB, other members increment from 01 to 02, 03, etc
                if (PersonSequenceNumber != "01")
                {
                    return FamilyName + "01";
                }
                else
                {
                    return null;
                }
            }
        }

        public string HeadOfHouseholdPrincipalKey
        {
            get
            {
                return FamilyName + PersonSequenceNumber;

            }
        }
    }
}

Upvotes: 0

Views: 1479

Answers (2)

Sylwester Zarębski
Sylwester Zarębski

Reputation: 415

It is not possible to have relation in EF Core, which is not defined using database beneath. You are trying to use foreign key by using read-only property and this is not supported.

If You simply want to .Include() Person table, You maybe could use composite key:

.HasForeignKey(p => new { p.FamilyName, p.PersonSequenceNumber) });

See examples at: EF Core Relations #Foreign key and EF Core Relations #Principal key

PS. I suppose principal key should be from referenced table, not current:

.HasPrincipalKey(parent => parent.HeadOfHouseholdPrincipalKey);

Upvotes: 1

evilmandarine
evilmandarine

Reputation: 4553

When creating your model, you need to map exactly what is in the database. So if I understand correctly what you're trying to do, you need to do 2 things:

  1. Remove these declarations for the columns that are not in the database. You need a primary key in the database and that's the only thing you need to declare when creating your model:

    // Remove these as these fields are not in the DB
    .HasForeignKey(p => p.HeadOfHouseholdForeignKey)
    .HasPrincipalKey(p => p.HeadOfHouseholdPrincipalKey);
    
  2. Add the NotMapped attribute to the properties that do not have a column in the database as follows:

    [NotMapped]
    public string HeadOfHouseholdForeignKey
    // ...
    
    [NotMapped]
    public string HeadOfHouseholdPrincipalKey
    // ...
    

Upvotes: 0

Related Questions