Consider the following Entity Framework Core 6.0 model classes:
public class Person
{
public int Id { get; set; }
[Required]
public int? PrimaryAddressId { get; set; }
public Address? PrimaryAddress { get; set; }
public int? SecondaryAddressId { get; set; }
public Address? SecondaryAddress { get; set; }
}
public class Address
{
public int Id { get; set; }
public List<Person> People { get; set; } = new();
}
From a functionality perspective, I want to be able to load an Address
with any and all People
related to that Address
, and each Person
will have at least one primary Address
.
Does Entity Framework support mapping multiple foreign key/reference navigation properties in one model class to a single collection navigation property in another? If so, how is that expressed?
CodePudding user response:
You can set it up using multiple collection properties on Address
:
public class Person
{
public int Id { get; set; }
[Required]
public int PrimaryAddressId { get; set; }
public Address PrimaryAddress { get; set; }
public int? SecondaryAddressId { get; set; }
public Address? SecondaryAddress { get; set; }
}
public class Address
{
public int Id { get; set; }
public List<Person> PrimaryPeopleAddresses { get; set; } = new();
public List<Person> SecondaryPeopleAddresses { get; set; } = new();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.HasOne(person => person.PrimaryAddress)
.WithMany(a => a.PrimaryPeopleAddresses);
modelBuilder.Entity<Person>()
.HasOne(person => person.SecondaryAddress)
.WithMany(a => a.SecondaryPeopleAddresses);
}
Also since primary address is required it should not be marked as nullable.
CodePudding user response:
No, it is not possible to have one navigation collection in one entity (Address.People
) which is mapped to multiple navigation properties in the other entity (Person.PrimaryAddress
and Person.SecondaryAddress
). You can try setting this up in your OnModelCreating()
method like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Address>()
.HasMany<Person>(p => p.People)
.WithOne(p => p.PrimaryAddress)
.HasForeignKey(p => p.PrimaryAddressId);
modelBuilder
.Entity<Address>()
.HasMany<Person>(p => p.People)
.WithOne(p => p.SecondaryAddress)
.HasForeignKey(p => p.SecondaryAddressId);
modelBuilder
.Entity<Person>()
.HasOne<Address>(p => p.PrimaryAddress)
.WithMany(p => p.People)
.HasForeignKey(p => p.PrimaryAddressId);
modelBuilder
.Entity<Person>()
.HasOne<Address>(p =>p.SecondaryAddress)
.WithMany(p => p.People)
.HasForeignKey(p => p.SecondaryAddressId);
}
However, this will result in an exception eventually:
System.InvalidOperationException: Cannot create a relationship between 'Address.People' and 'Person.SecondaryAddress' because a relationship already exists between 'Address.People' and 'Person.PrimaryAddress'. Navigations can only participate in a single relationship. If you want to override an existing relationship call 'Ignore' on the navigation 'Person.SecondaryAddress' first in 'OnModelCreating'