Hi,
I've been building my first few Radzen LOB apps and have encountered the bizarre choice for the default Cascade Delete behaviour in EF Core. I've read through the various posts on how to disable it but find that the Radzen app's behaviour produces unexpected behaviour with some settings. I'd like to highlight the issues with some of those settings and get feedback, as well as confirm whether the workaround is actually the correct way to do this in Radzen.
Information
- Windows 10
- Radzen version 2.50.14
- EF Core version 3.1.4
App Setup
- Set up a SQL DB with two basic entities, a Product and a Subscription. A Subscription is required to have a product through a Foreign Key constraint and is marked as not null.
- Set up a basic Radzen Blazor App with "Enable cascade delete" unchecked during the data import.
- Create a .partial.cs file for the DataContext and specify the OnModelBuilding method to change the delete behaviour to Restrict, since this seems to be the appropriate one:
partial void OnModelBuilding(ModelBuilder builder)
{
var cascadeFKs = builder.Model.GetEntityTypes()
.SelectMany(t => t.GetForeignKeys())
.Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);
foreach (var fk in cascadeFKs)
fk.DeleteBehavior = DeleteBehavior.Restrict;
}
- Run the app and create a product, and then create a subscription associated with that product.
Steps to reproduce issues:
- Run the app from a fresh start. The existing products are listed.
- Create a new product. The product is created, as expected.
- List the subscriptions.
- Return to the products list and attempt to delete the associated product. As expected, the delete fails with the error "Unable to delete Product".
- Attempt to create a new Product, this unexpectedly fails with the error "Unable to create new Product".
Expected Behaviour
The product creation in step 4 is expected to succeed, regardless of whether or not you have browsed to the subscriptions.
Workaround
Change the delete behaviour to DeleteBehavior.ClientNoAction
Details
Issue 1:
In the DeleteProduct method, the call to Remove now throws an exception (as opposed to only when SaveChanges is called). This appears to be a breaking change in EF Core 3, so the catch block won't get hit.
Issue 2:
Even if you prevent from Remove from throwing the exception and get SaveChanges to do so, the broken relationship is still in the ChangeTracker after the product is deleted. I'm not even sure how you discard this from the ChangeTracker, or if you're even meant to? It seems like this occurs specifically when you browse to subscriptions because it results in the Subscription being tracked.
Questions
- Is the workaround with DeleteBehavior.ClientNoAction the right way to achieve the disabling of Cascade delete for a Radzen app? I ask because the value's documentation says "It is unusual to use this value. Consider using DeleteBehavior.ClientNoAction instead to match the behaviour of EF6 with cascading deletes disabled."
- Given the behaviour in Issue 2, it seems like we can't use DeleteBehavior.Restrict or another setting which results in exceptions being thrown. Are we meant to avoid these settings for specific entities?
That's a lot to read, sorry And thanks for creating a product like this...it makes life the front-end prototyping so much less painful.