Entity Framework Core One-to-Many Relationship is established between 2 entities by the use of Fluent APIs. This relationship is configured 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. We can use either one from the below 2 Has/With pattern to create a relationship.
Page Contents
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; }
We will create the Entity Framework Core One-to-Many Relationship with Fluent API for these 2 entities by overriding the OnModelCreating method in the Database Context class, as shown below.
public class CountryContext: DbContext
{
public DbSet<City> City { get; set; }
public DbSet<Country> Country { get; set; }
public CountryContext(DbContextOptions<CountryContext> options) : base(options)
{
}
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 we will get Country and City database tables created having foreign key as FKCountry on the City table.
You can also configure the same One-to-Many Relationship by using the HasMany – WithOne pattern. So in this case we start with Country 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);
EF Core behaves differently when the parent entity of the foreign key is deleted. We can configure this using Fluent API. We can instruct EF Core to delete the child row from the db table 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, we 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:
We have some names of Cities and Countries in the database tables, as shown by the below image.
Now we will delete Country having an Id ‘1’ from the Country table using the below EF Core code:
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 where we have shown the snapshot of the 2 tables after executing the delete. This proves the cascade delete is working properly.
Download the source code: