Configure One-to-Many relationship using Fluent API in Entity Framework Core

Configure One-to-Many relationship using Fluent API in Entity Framework Core

Entity Framework Core makes it very easy for us to configure relationships using Fluent APIs. In this tutorial I will explain how to configure One-to-Many relationship using Fluent API.

Note: Conventions in Entity Framework Core can also be used to create any type of relationships.

A Relationship is established by the use of Has/With pattern. The Has side of the pattern has 2 variants which are HasOne() and HasMany() methods. The With side of the pattern has 2 variants which are WithOne() and WithMany() methods.

You can use any one variant from each side of the Has/With pattern to create a Relationship.

The One-to-Many Relationship is established by using either one from the below 2 Has/With pattern:

  • HasOne – WithMany
  • HasMany – WithOne

Consider the following Country and City entities.

public class Country
{
    public int Id { get; set; }
 
    public string Name { get; set; }
 
    public ICollection<City> City { get; set; }
}

public class City
{
    public int Id { get; set; }
 
    public string Name { get; set; }
 
    public int FKCountry { get; set; }
 
    public Country Country { get; set; }
}

The Country entity has a Collection Navigation Property called City.

public ICollection<City> City { get; set; }

The City entity has a Reference Navigation Property called Country.

public Country Country { get; set; }

I will Configure the One-to-Many Relationship for these 2 entities using Fluent API by overriding the OnModelCreating method in the Database Context class, as shown below.

public class CompanyContext : DbContext
{
    public DbSet<City> City { get; set; }
    public DbSet<Country> Country { get; set; }
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(@"Server=vaio;Database=Company;Trusted_Connection=True;");
        }
    }
 
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //Write Fluent API configurations here
 
        modelBuilder.Entity<City>()
                    .HasOne(e => e.Country)
                    .WithMany(e => e.City)
                    .HasForeignKey(e => e.FKCountry)
                    .OnDelete(DeleteBehavior.Cascade);;
    }
}

On performing EF Core Migrations you will get Country and City database tables created having foreign key as FKCountry on the City table.

one to many relationship

Understanding how One-to-Many Relationship is configured

  • Start by configuring one entity (either Country or City class). I start with City class (modelBuilder.Entity).
  • Next, I use the Has/With pattern, and by using the .HasOne(e => e.Country) method I specify that the entity contains the reference navigation property of other type (i.e. Country). This creates the one-to-many relationship between them.
  • Next, I move to the other end of the relationship, and by using the .WithMany(e => e.City) method I specify that the Country entity includes collection navigation property of the City type.
  • The .HasForeignKey(e => e.FKCountry) specifies that the property called FKCountry is the foreign key for the City table.
In the above code I have used the HasOne – WithMany pattern to create the One-to-Many Relationship between the City and Country entities.

You can also configure the One-to-Many Relationship by using the HasMany – WithOne pattern. So in this case you start with Country entity instead of the City entity and then create this relationship as shown by the below code:

modelBuilder.Entity<Country>()
            .HasMany(e => e.City)
            .WithOne(e=>e.Country)
            .HasForeignKey(e => e.FKCountry);

Cascade Delete in Fluent API for Foreign Keys

EF Core behaves differently when the parent entity of the foreign key is deleted. You can configure this using Fluent API. You can instruct EF Core to – delete the child row if the related parent row is deleted, or set foreign key to null, or prevent delete.

This is done from .OnDelete() method.

On the below code I have set ‘DeleteBehaviour’ as Cascade which means the dependent entity will be deleted when its parent entity is deleted.

modelBuilder.Entity<City>()
            .HasOne(e => e.Country)
            .WithMany(e => e.City)
            .HasForeignKey(e => e.FKCountry)
            .OnDelete(DeleteBehavior.Cascade); //Cascade behaviour

The DeleteBehaviour has 4 values:

  • Cascade : Dependent entities will be deleted if its principal entity is deleted.
  • ClientSetNull: The values of foreign key properties in the dependent entities will be set to null when its parent entity is deleted.
  • Restrict: Prevents Cascade delete.
  • SetNull: The values of foreign key properties in the dependent entities will be set to null when its parent entity is deleted.

Cascade delete Example

I have name of Cities and names of Countries in the database tables, as shown by the below image.

cascade delete one to many

Now I will delete Country having an Id ‘1’ from the Country table using the below EF Core code:

using (var context = new CompanyContext())
{
    Country country = new Country()
    {
        Id = 1
    };

    context.Remove(country);
    await context.SaveChangesAsync();
}

Since the configuration is set for Cascade Delete then all the cities associated with the country having id ‘1’ are also deleted automatically. See the below picture which shown this information.

cascade delete one to many

Download the source code:

DOWNLOAD

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.