Created | ![]() |
Favourites | Opened | Upvotes | Comments |
21. Sep 2019 | 3 | 0 | 258 | 0 | 0 |
In EF Core database cascade behavior is controlled using the DeleteBehavior enum in the OnModelCreation member of the Context class.
A common way to extend the Context class is like this :
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
// setup db tables here
protected override void OnModelCreating(ModelBuilder builder)
{
// define cascade behavior here
}
}
So say we have 2 Entity classes, Topic & Comment :
// Principal (parent) class
public class Topic
{
public int Id { get; set; }
public string Name { get; set; }
public string Body { get; set; }
public ICollection<Comment> Comments { get; set; } // navigation property
}
// Dependent (child) class
public class Comment
{
public int Id { get; set; }
public string Body { get; set; }
public int TopicId { get; set; }
[ForeignKey("TopicId")] // could alternatively be set by Fluent API
public Topic Topic { get; set; } // navigation property
}
The above 2 entities, Topic & Comment, each have one navigation property, which implicitly specifies a one-to-many relationship between the 2 classes. Note that a navigation property is any property that does NOT map to a built-in datatype in the database provider. There are 2 types of navigation properties :
Let's start to set it up first specifying the 2 tables to create using the DbSet class to map Entities to tables :
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Topic> Topics;
public DbSet<Comment> Comments;
protected override void OnModelCreating(ModelBuilder builder)
{
// define cascade behavior here
}
}
After specifying the tables we need to override the Context.OnModelCreating member to specify database properties like Keys, Indexes, Cascade behaviour (and many more).
Notice the ModelBuilder instance passed as a parameter to the OnModelCreating member - the ModelBuilder exposes the EF Core Fluent API, which we use to specify the above database properties (though here we focus only on cascade behaviour).
EF Core Fluent API have many methods, but only a few are relevant for cascade behaviour :
A relationship between 2 entities is said to be either Required or Optional. If the dependent CANNOT exist without the principal (the foreign key is NOT nullable), the relationship is Required. Eg. in our case a Comment gives no meaning if it does not belong to a Topic - the relationship between Topics & Comments is therefore Required. If the dependent CAN exist without the principal (the foreign key is nullable), the relationship is Optional.
Finally we can finish our Context class :
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Topic> Topics;
public DbSet<Comment> Comments;
protected override void OnModelCreating(ModelBuilder builder)
{
// delete dependents (this is btw default behaviour for required relationships)
builder.Entity<Comment>.HasOne(t => t.Topic).WithMany(c => c.Comments).OnDelete(DeleteBehavior.Cascade);
}
}
In many cases we don't need to explicitly set the DeleteBehavior but can rely on the default behavior which depends on whether the relationship between 2 entities is