How to: Set Up Cascade Delete With Multi-Table Entities
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 mapped to a multi-table entity, by default, results in a DELETE statement against the main table and multiple DELETE statements against those that hold properties of the entity. In cases when the entity is separated between a lot of tables, 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 main table and will rely on the backend to delete the related records from the other tables.
Telerik Data Access offers two ways to control the usage of cascade delete in fluent models that have multi-table entities structures:
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 [Categories] ADD CONSTRAINT [ref_Categories_Products] FOREIGN KEY ([CategoryID]) REFERENCES [Products]([Id]) ON DELETE CASCADE go ALTER TABLE [Orders] ADD CONSTRAINT [ref_Orders_Products] FOREIGN KEY ([OrderID]) REFERENCES [Products] ([Id]) ON DELETE CASCADE go
-
If you attempt to delete the first object of the entity, you will notice that Telerik Data Access issues a DELETE statement only against the Products table:
using (FluentModel dbContext = new FluentModel()) { Product firstProduct = dbContext.Products.FirstOrDefault(); dbContext.Delete(firstProduct); dbContext.SaveChanges(); }
Using dbContext As New FluentModel() Dim firstProduct As Product = dbContext.Products.FirstOrDefault() dbContext.Delete(firstProduct) dbContext.SaveChanges() End Using
The SQL generated would be similar to the following:
```SQL
DELETE FROM [Products] WHERE [Id] = @p0
```
The value of AllowCascadeDelete will influence the constraints between the tables that form the multi-table entity and between tables participating in vertical inheritance only.
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 multi-table entity.
The workflow for enabling it includes the following steps:
-
In the mapping configuration of the entity, add a call to the WithCascadeDelete() method (or to WithCascadeDelete(CascadeDeleteOption.Yes)):
configuration.MapType().WithCascadeDelete(CascadeDeleteOption.Yes).ToTable("Products");
configuration.MapType().WithCascadeDelete(CascadeDeleteOption.Yes).ToTable("Products")
-
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 all of the constraints between the tables are (re)created to allow cascade delete. For example:
ALTER TABLE [Categories] ADD CONSTRAINT [ref_Categories_Products] FOREIGN KEY ([CategoryID]) REFERENCES [Products] ([Id]) ON DELETE CASCADE go ALTER TABLE [Orders] ADD CONSTRAINT [ref_Orders_Products] FOREIGN KEY ([OrderID]) REFERENCES [Products] ([Id]) ON DELETE CASCADE go
You can test the removal of the objects from the multi-table entity structure as shown here.
Choosing CascadeDeleteOption.No will explicitly disable the usage of cascade delete for the particular multi-table entity. CascadeDeleteOption.Default will respect the value of the AllowCascadeDelte property of the runtime configuration.