Search code examples
c#entity-frameworkdbcontextef-core-2.2

Setup one to many relation with fk having multiple rows


I have a problem with setting up a one-to-many relation with EF Core.
I have two tables address and address_country. There are schemas: address table schema
address_country table schema
As you see, I want to store countries with different locales. So it has a composed key. address table has a foreign key to address_country. Unfortunately, I cannot setup ContextDb to achieve what I want. The list of countries is not filled in Address model.
I have the following code in Context:

public class Context : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite(
            @"Data Source=addresses.db");
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AddressDto>()
            .ToTable("address");

        modelBuilder.Entity<CountryLocaleDto>()
            .ToTable("address_country");

        modelBuilder.Entity<CountryLocaleDto>()
            .HasKey(cl => new {cl.Id, cl.Locale});

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<AddressDto> Addresses { get; set; }
}

And my models are

public class AddressDto
{
    public int Id { get; set; }
    public int CountryId { get; set; }
    public List<CountryLocaleDto> CountryLocale { get; set; }
}
public class CountryLocaleDto
{
    public int Id { get; set; }
    public string Locale { get; set; }
}

There is no exception. I simply don't know how to configure this kind of relation. Can anyone help me with that, please?

Example data would be:
address

id countryId
1 1
2 1

address_country

id locale name
1 'en' 'Germany'
1 'de' 'Deutschland'

An example solution with SQLite db can be found with this link.


Solution

  • If I got you right - you just need to add this code to your context class

    modelBuilder.Entity<AddressDto>()
                .HasMany(e=>e.CountryLocale)
                .WithOne()
                .HasForeignKey(x=>x.Id)
                .HasPrincipalKey(x=>x.CountryId);
    

    Here you have to add HasForeignKey and HasPrincipalKey

    The Entity Framework Core Fluent API HasForeignKey method is used to specify which property is the foreign key in a relationship.

    Principal key: The property(s) that uniquely identifies the principal entity. This may be the primary key or an alternate key. Navigation property: A property defined on the principal and/or dependent entity that contains a reference(s) to the related entity(s).

    your model should look like that

    public class AddressDto
    {
        public int Id { get; set; }
        public int CountryId { get; set; }
        public List<CountryLocaleDto> CountryLocale { get; set; }
    }
    public class CountryLocaleDto
    {
        public int Id { get; set; }
        public string Locale { get; set; }
    }
    

    I mean you don't have to add anything else in your model.

    I hope it was helpful.

    P.S. Appreciate adding the sample project