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

Non-nullable FK's get On Delete Behavior of ClientSetNull when scaffolding #9935

Closed
jjwilliams42 opened this issue Oct 1, 2017 · 3 comments

Comments

@jjwilliams42
Copy link

Maybe I'm misunderstanding what ClientSetNull does, but when using dotnet ef dbcontext scaffold, if I have a required relationship from a child to a parent (non-nullable foreign key), scaffold always generates the modelBuilder with ClientSetNull behavior on delete.

I'm not sure why, the field in the database is not null, the property generated is not nullable.
The documentation (when hovering) states:

"This is the default for optional relationships. That is, relationships that have nullable foreign keys".

Expected behavior:

DeleteBehavior.Cascade is used instead. If a child has a non-nullable FK that indicates it cannot live without the parent. If the parent dies, so must the child.

Or maybe I'm misunderstanding something and need to quit coding after 2AM :>.

Steps to reproduce

Create Database

CREATE DATABASE [Test2]
GO

USE [Test2]
GO
/****** Object:  Table [dbo].[Posts]    Script Date: 10/1/2017 2:37:29 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Posts](
	[Id] [int] NOT NULL,
	[UserId] [int] NOT NULL,
	[PostContent] [varchar](max) NOT NULL,
 CONSTRAINT [PK_Posts] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[Users]    Script Date: 10/1/2017 2:37:29 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Users](
	[Id] [int] NOT NULL,
	[UserName] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
ALTER TABLE [dbo].[Posts]  WITH CHECK ADD  CONSTRAINT [FK_Posts_Users] FOREIGN KEY([UserId])
REFERENCES [dbo].[Users] ([Id])
GO
ALTER TABLE [dbo].[Posts] CHECK CONSTRAINT [FK_Posts_Users]
GO

Scaffold

dotnet ef dbcontext scaffold "Data Source=.\SQLExpress;Integrated Security=True;Database=Test;MultipleActiveResultSets=True" Microsoft.EntityFrameworkCore.SqlServer -c TestContext -o Models

Output

           entity.HasOne(d => d.User)
                    .WithMany(p => p.Posts)
                    .HasForeignKey(d => d.UserId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Posts_Users");

Project Link

https://1drv.ms/u/s!Aig3X163M_PDg7U24JBJH1gamRQpCw

Further technical details

EF Core version: 2
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2017 15.3.5

@divega
Copy link
Contributor

divega commented Oct 1, 2017

@jackjwilliams Required relationships default to DeleteBehavior.Cascade and optional relationships default to DeleteBehavior.ClientSetNull only if no other DeleteBehavior is configured explicitly.

The documentation describes the behavior of the EF Core runtime, but it seems in this case DbContext scaffolding is resulting in an explicit configuration, so the defaults are not applied:

                    .OnDelete(DeleteBehavior.ClientSetNull)

I suspect we may be doing this on purpose because there is no ON DELETE CASCADE specified in the database, although I would like us to take a closer look (perhaps Restrict would have been more appropriate in this case).

@ajcvickers
Copy link
Member

Notes from triage: ClientSetNull for a required relationship (non-nullable FK) means that if an attempt is made to set the FK to null, then an exception will be thrown on SaveChanges. This is functionally correct for this case, but after the change to Restrict in #9703 it might be clearer to start reverse engineering to Restrict at that time. Closing this as a dupe of #9703 with a note on #9703 to update reverse engineering.

@jjwilliams42
Copy link
Author

Thanks for the triage and explanation of what exactly this does.

The documentation on the enum was confusing and I'm not sure if it ever just came out and said "ClientSetNull for a required relationship (non-nullable FK) means that if an attempt is made to set the FK to null, then an exception will be thrown on SaveChanges" ... Which I think relates to #9687.

@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
None yet
Projects
None yet
Development

No branches or pull requests

3 participants