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

SqlServer FillFactor for PK is missing #32803

Closed
bryanhunwardsen opened this issue Jan 12, 2024 · 6 comments · Fixed by #32900
Closed

SqlServer FillFactor for PK is missing #32803

bryanhunwardsen opened this issue Jan 12, 2024 · 6 comments · Fixed by #32900
Labels
area-migrations area-sqlserver closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. community-contribution customer-reported type-enhancement

Comments

@bryanhunwardsen
Copy link

bryanhunwardsen commented Jan 12, 2024

"FillFactor" was added several versions ago but it is incomplete/broken.
.HasFillFactor() is only settable on explicit/defined Indexes.
In SqlServer, FillFactor can be set on the PK without additional complexity to the Schema.
This is not available with the FillFactor implementation of EFC 8.
This is an incomplete implementation of the feature which is why I am filing as a bug and not as a feature request.

To advertise FillFactor is supported in EF, code like this:

builder.HasKey(x => x.Id).HasFillFactor(90);

Should produce Sql Schema as:

CREATE TABLE [dbo].[MyTable](
	[Id] [int] IDENTITY(1,1) NOT NULL
 CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

or at a minimum, provide a fluent option that ultimately executes the following sql as it will cover the PK:

ALTER TABLE MyTable REBUILD WITH (FILLFACTOR = 90);
GO

EF Core version: 8
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Win10
IDE: Visual Studio 2022 17.4

@roji
Copy link
Member

roji commented Jan 12, 2024

Yeah, this makes sense. For now, you can insert the ALTER TABLE SQL directly in your migrations to work around this.

@roji roji added the good first issue This issue should be relatively straightforward to fix. label Jan 12, 2024
@bryanhunwardsen
Copy link
Author

Yeah, this makes sense. For now, you can insert the ALTER TABLE SQL directly in your migrations to work around this.

Unfortunately this is not the case, if the migration epoch is reset, or just rolled back/deleted and regenerated, these changes are lost, would have to be manually reapplied, and are therefore not sufficiently durable. (This is exactly the use case I am addressing currently)

I was able to implement a custom CSharpMigrationOperationGenerator that injects the FillFactor sql script into into the migration Up for each TableCreate and TableAlter Up operations, it is oversimplified, heavy handed, and fragile. Still would prefer a proper fluent implementation from EFCore.

@roji
Copy link
Member

roji commented Jan 13, 2024

Unfortunately this is not the case, if the migration epoch is reset, or just rolled back/deleted and regenerated, these changes are lost, would have to be manually reapplied, and are therefore not sufficiently durable. (This is exactly the use case I am addressing currently)

That's true, but this amounts to saying that SQL can never be used in migrations; we're unfortunately unable to provide built-in migration support for each and every supported feature of all databases out there - there's far too many, and modeling all the possibilities of all DDL variants is simply unfeasible.

I do agree we should implement this (after all we do have it for indexes) - I'm just saying that it's unlikely to be prioritized. It's also not an very difficult thing to do, if you're interested in contributing it.

@ajcvickers ajcvickers added this to the Backlog milestone Jan 17, 2024
@deano-hunter
Copy link
Contributor

I would be interested in picking this up as a first issue.

It looks like adding the WITH options and including FILLFACTOR for primary keys to the SQL Generators is what is needed so that HasFillFactor can be used with key properties.

Looking through the code, this looks relatively straight forward. While there will be a few changes to handle adding the FillFactor constant for primary keys, the main code will be in the SqlServerMigrationsSqlGenerator, SqlServerKeyExtensions, SqlServerKeyBuilderExtensions classes.

@bryanhunwardsen
Copy link
Author

I would be interested in picking this up as a first issue.

It looks like adding the WITH options and including FILLFACTOR for primary keys to the SQL Generators is what is needed so that HasFillFactor can be used with key properties.

Looking through the code, this looks relatively straight forward. While there will be a few changes to handle adding the FillFactor constant for primary keys, the main code will be in the SqlServerMigrationsSqlGenerator, SqlServerKeyExtensions, SqlServerKeyBuilderExtensions classes.

Please note, .HasAlternateKey() should be included with this work to fill the gap to a complete feature.

@ajcvickers
Copy link
Member

@deano-hunter Sounds good; go for it!

deano-hunter pushed a commit to deano-hunter/efcore that referenced this issue Jan 23, 2024
@ajcvickers ajcvickers modified the milestones: Backlog, 9.0.0 Feb 16, 2024
@ajcvickers ajcvickers added closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. community-contribution and removed good first issue This issue should be relatively straightforward to fix. labels Feb 16, 2024
@ajcvickers ajcvickers modified the milestones: 9.0.0, 9.0.0-preview2 Feb 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations area-sqlserver closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. community-contribution customer-reported type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants