How to: Set Up Cascade Delete With Vertical Inheritance
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
Deleting objects from database tables participating in vertical inheritance, by default, results in a DELETE statement against the table mapped to the base persistent class and multiple DELETE statements against those mapped to derived classes. In cases when the class hierarchy is separated on a lot of levels, this may cause a low performance rate of the application.
Telerik Data Access helps you to solve this issue while you create the fluent model by allowing you to set the delete rule of the constraints between the tables to CASCADE. After the database is synchronized with this setting, Telerik Data Access will issue DELETE statements only against the base table and will rely on the backend to delete the related records from the derived tables.
Telerik Data Access offers two ways to control the usage of cascade delete in fluent models that have vertical inheritance hierarchies:
The usage of cascade delete varies according to the settings on both model and class level as follows:
Model | Class | Cascade Delete Usage |
Enabled | Default | True |
Enabled | Yes | True |
Enabled | No | False |
Diabled | Default | False |
Diabled | Yes | True |
Diabled | No | False |
Cascade Delete on Fluent Model Level
The usage of CASCADE delete for the whole fluent model is enabled and disabled through the AllowCascadeDelete property of the RuntimeConfiguration class.
The workflow for enabling it includes the next steps:
-
In the backend configuration used by the context, set AllowCascadeDelete property to True. For example:
public static BackendConfiguration GetBackendConfiguration() { BackendConfiguration backend = new BackendConfiguration(); backend.Runtime.AllowCascadeDelete = true; backend.Backend = "MsSql"; backend.ProviderName = "System.Data.SqlClient"; return backend; }
Public Shared Function GetBackendConfiguration() As BackendConfiguration Dim backend As BackendConfiguration = New BackendConfiguration() backend.Runtime.AllowCascadeDelete = True backend.Backend = "MsSql" backend.ProviderName = "System.Data.SqlClient" Return backend End Function
-
With the help of the UpdateSchema() method, migrate the fluent model to the database. If you look through the script this method produces, you will notice that all of the constraints between the tables which form the entity are (re)created to allow cascade delete. For example:
ALTER TABLE [Cat] ADD CONSTRAINT [ref_Cat_Animal] FOREIGN KEY ([AnimalId]) REFERENCES [Animal] ([AnimalId]) ON DELETE CASCADE go ALTER TABLE [Dog] ADD CONSTRAINT [ref_Dog_Animal] FOREIGN KEY ([AnimalId]) REFERENCES [Animal] ([AnimalId]) ON DELETE CASCADE go ALTER TABLE [WienerDog] ADD CONSTRAINT [ref_WienerDog_Dog] FOREIGN KEY ([AnimalId]) REFERENCES [Dog] ([AnimalId]) ON DELETE CASCADE go
-
If you attempt to delete the first Animal object, you will notice that Telerik Data Access issues a DELETE statement only against the Animal table:
using (FluentModel dbContext = new FluentModel()) { Animal firstAnimal = dbContext.Animals.FirstOrDefault(); dbContext.Delete(firstAnimal); dbContext.SaveChanges(); }
Using dbContext As New FluentModel() Dim firstAnimal As Animal = dbContext.Animals.FirstOrDefault() dbContext.Delete(firstAnimal) dbContext.SaveChanges() End Using
The SQL generated by Telerik Data Access would be similar to the following:
DELETE FROM [Animal] WHERE [AnimalId] = @p0
The value of AllowCascadeDelete will influence the constraints between the tables that build the vertical inheritance hierarchy and between the tables that form Multi-Table Entities only. Additionally, if a base class is explicitly set to use (or not use) cascade delete on class level, Telerik Data Access will disregard the value of AllowCascadeDelete and take into account the class' setting when it generates DELETE statements against the tables mapped to its derived classes.
Cascade Delete on Class Level
Since a fluent model can contain a variety of entities connected with one another in different ways, you may need to control the usage of CASCADE delete only for a particular vertical inheritance hierarchy.
The workflow for enabling it includes the following steps:
-
In the mapping configuration of a base class, add a call to the WithCascadeDelete() method (or to WithCascadeDelete(CascadeDeleteOption.Yes)):
configuration.MapType().WithCascadeDelete(CascadeDeleteOption.Yes).ToTable("Dog");
configuration.MapType().WithCascadeDelete(CascadeDeleteOption.Yes).ToTable("Dog")
-
In scenarios when you do not need to use cascade delete on fluent model level, set the AllowCascadeDelete to False:
backend.Runtime.AllowCascadeDelete = false;
backend.Runtime.AllowCascadeDelete = False
-
With the help of the UpdateSchema() method, migrate the fluent model to the database. If you look through the script this method produces, you will notice that only the constraints between the base table and the derived tables are (re)created to allow cascade delete. For example:
ALTER TABLE [WienerDog] ADD CONSTRAINT [ref_WienerDog_Dog] FOREIGN KEY ([AnimalId]) REFERENCES [Dog]([AnimalId]) ON DELETE CASCADE go
You can test the removal of objects from the hierarchy as shown here.
Choosing CascadeDeleteOption.No will explicitly disable the usage of cascade delete for a particular base class. CascadeDeleteOption.Default will respect the value of the AllowCascadeDelte property of the runtime configuration.