Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DeleteBehavior.Restrict behaves like ClientSetNull #18959

Closed
Neme12 opened this issue Nov 17, 2019 · 5 comments
Closed

DeleteBehavior.Restrict behaves like ClientSetNull #18959

Neme12 opened this issue Nov 17, 2019 · 5 comments
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@Neme12
Copy link

Neme12 commented Nov 17, 2019

DeleteBehavior.Restrict seems to behave exactly like ClientSetNull. Looking at the docs https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.deletebehavior?view=efcore-3.0, I can't see any difference between Restrict and ClientSetNull. Is there any?

This was very unexpected to me because I expected Restrict to just show a database error if I delete the referenced entity as opposed to EF Core silently setting the foreign key to null. Instead, I spent a lot of time debugging and wondering how the column could have become null. If Restrict behaves like ClientSetNull, is there any option that actually behaves like restrict and opt-out of EF Core interfering with my foreign keys and silently setting them to null?

My scenario for this is:
I have a parent entity and child entities with cascading delete behavior. One of the children is special and is needed almost every time the parent entity is needed, and to simplify a lot of queries, we introduced a foreign key that points from the parent entity to this single child entity. It has to be nullable because it's not possible to create a cyclic dependency with one query (because the entities don't have IDs yet). The DeleteBehavior should be Restrict because deleting this child entity should never delete the parent - deleting the child entity while there's a reference to it from the parent is always a bug in the code (the key needs to be changed to point to a different child entity - it shouldn't ever be null except for the purpose of creating the cyclic dependency). If Restrict didn't have the set null behavior, I could have caught this bug early.

@ajcvickers
Copy link
Member

@Neme12 Restrict changes what the database does without changing what EF does. ClientNoAction stops EF from nulling an FK property when the principal entity is deleted.

@ajcvickers ajcvickers added closed-no-further-action The issue is closed and no further action is planned. and removed type-bug labels Nov 18, 2019
@Neme12
Copy link
Author

Neme12 commented Nov 18, 2019

@ajcvickers I would argue that the name is confusing then. Restrict sounds like it should behave like database restrict without any fixup behavior from EF Core.

Restrict changes what the database does

But ClientSetNull sets the database referential action to Restrict as well. So what's the difference between them?

@Neme12
Copy link
Author

Neme12 commented Nov 18, 2019

@ajcvickers I think I see your point now. So Restrict changes what the database does (often it doesn't because ReferentialAction.Restrict is the default), but doesn't change what EF Core does, whereas ClientSetNull/ClientNoAction affect what EF Core does without changing what the database does?

This design seems really unfortunate because the enum is not a flags enum which means that I cannot set the database behavior Restrict and EF Core behavior ClientSetNull at the same time. Or is that possible using two OnDelete calls? If that's the case, then that's even more confusing.

Also, I don't see how it would make any sense to set some EF Core fixup behavior (like ClientSetNull or ClientCascade) and a referential action other than Restrict in the database as well. It seems to me that setting Restrict should set the referential action to Restrict and disable any EF Core fixup, whereas ClientSetNull and ClientCascade would also set the referential action to Restrict while enabling appropriate EF Core fixup. Then there would be no need for ClientNoAction. This is what I thought the API was doing.


In any case, the API is really confusing as it is right now.

@ajcvickers
Copy link
Member

@Neme12 This may be helpful: #12661 (comment)

@markusschaber
Copy link

This change is really confusing, and broke our app while upgrading from 2.1 to 3.1.

Having "Restrict" not actually restricting, but like ClientSetNull is misleading.

I'm not against having an option for that behaviour, but shipping it with the name "Restrict" which used to restrict deletions in earlier versions is just a hidden trap, close to perfidiousness!

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

3 participants