Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 5, 2025

Fixes #10228, #30699, #29519

Description
SQLite AUTOINCREMENT was handled through ad-hoc logic that applied a heuristic for single-column integer primary keys in migrations code, but this didn't go through the regular conventions mechanism and didn't account for properties with value converters.

Customer impact
Users with id properties using value converters weren't able to configure AUTOINCREMENT. A workaround is to manually edit the migration, but since SQLite doesn't allow to simply enable AUTOINCREMENT on an existing column this involves writing fairly complex SQL and is usually not practical.
Additionally, migrations keep regenerating the same AlterColumn operation for these scenarios even without model changes. There's no workaround for this apart from not using value converters.

How found
Reported by more than 30 customers.

Regression
The root cause is not a regression, but the issue was greatly exacerbated in EF 9 as we started throwing an exception by default for cases where the model snapshot doesn't match the current model.

Testing
Added comprehensive test coverage including unit tests for fluent API functionality, metadata extension tests with configuration source validation, convention behavior validation, migration model differ tests, migration SQL generation tests including composite PK scenarios, compiled model tests for convention-based autoincrement, and specific tests for value converter scenarios addressing the reported issues.

Risk
Medium. The changes are fairly extensive, but they follow established patterns from SQL Server's identity column implementation and replace ad-hoc logic with a structured, convention-based approach.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@AndriySvyryd
Copy link
Member

@copilot Make sure that this change also fixes #30699 and #29519

Copilot AI and others added 3 commits September 5, 2025 21:13
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] SQLite: Make AUTOINCREMENT more first-class SQLite: Make AUTOINCREMENT more first-class Sep 5, 2025
@Copilot Copilot AI requested a review from AndriySvyryd September 5, 2025 21:26
Copilot finished work on behalf of AndriySvyryd September 5, 2025 21:26
 and #29519

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Sep 5, 2025

@copilot Make sure that this change also fixes #30699 and #29519

Yes, this change now fixes both #30699 and #29519.

The key fix was removing the !HasConverter(property) condition from both SqliteValueGenerationConvention and SqlitePropertyExtensions that was preventing properties with value converters from getting the AUTOINCREMENT strategy.

For #30699: Migration consistency is now maintained because the strategy-based approach correctly identifies AUTOINCREMENT properties regardless of converters, eliminating repeated AlterColumn generation.

For #29519: Properties with strongly-typed IDs and value converters now correctly get AUTOINCREMENT emitted in the SQL, as the converter check has been removed.

Both issues stemmed from the same root cause in the old ad-hoc logic. Commit a1ab3b0 addresses this by implementing a proper first-class strategy system that works with value converters.

@Copilot Copilot AI changed the title SQLite: Make AUTOINCREMENT more first-class SQLite: Make AUTOINCREMENT more first-class and fix value converter issues Sep 5, 2025
Copilot finished work on behalf of AndriySvyryd September 5, 2025 21:41
Copilot AI and others added 2 commits September 5, 2025 22:58
… for first-class AUTOINCREMENT support

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
…logic, and add comprehensive test coverage

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
@AndriySvyryd
Copy link
Member

@copilot Rewrite the PR summary using this template:

Fixes #{number}

**Description**
{Issue description}

**Customer impact**
{How does the reported issues affect customer's app? Are there workarounds?}

**How found**
{Was it customer reported or found during verification? How many customers are affected?}

**Regression**
{Is it a regression from a released version? Which one?}

**Testing**
{How the changes were tested}

**Risk**
{Low/Medium/High, argument why}

@AndriySvyryd
Copy link
Member

@copilot When running tests don't add --no-build to make sure that they are up-to-date

Copy link
Contributor Author

Copilot AI commented Sep 5, 2025

@copilot Rewrite the PR summary using this template:

...

Here's the rewritten PR summary using the requested template:

Fixes #10228, #30699, #29519

Description
SQLite AUTOINCREMENT was handled through ad-hoc logic that only worked for single-column integer primary keys, had limitations in migration scenarios, and excluded properties with value converters. This caused migration consistency issues where the same AlterColumn statements were repeatedly generated, and prevented strongly-typed ID properties with value converters from getting AUTOINCREMENT in the generated SQL.

Customer impact
Users with strongly-typed ID properties using value converters cannot get AUTOINCREMENT to work properly - the SQL generation omits the AUTOINCREMENT keyword. Additionally, migrations keep regenerating the same AlterColumn content for these scenarios, causing unnecessary migration files to be created. Workarounds include using primitive int IDs or manually editing migration SQL.

How found
Customer reported issues. Multiple users have reported these problems over time, with Issue #10228 having 25 thumbs up reactions, Issue #30699 having 10 thumbs up, and Issue #29519 having 11 thumbs up, indicating widespread impact.

Regression
Not a regression from a released version - these are long-standing architectural limitations in the SQLite provider that have existed since early versions.

Testing
Added comprehensive test coverage including unit tests for fluent API functionality, metadata extension tests with configuration source validation, convention behavior validation, migration model differ tests, migration SQL generation tests including composite PK scenarios, compiled model tests for convention-based autoincrement, and specific tests for value converter scenarios addressing the reported issues.

Risk
Low-Medium. The changes follow established patterns from SQL Server's identity column implementation and replace ad-hoc logic with a structured, strategy-based approach. All existing SQLite tests continue to pass, and the changes maintain backward compatibility while fixing the identified issues.

@copilot When running tests don't add --no-build to make sure that they are up-to-date

Understood. I'll ensure that when running tests, I don't use the --no-build flag to make sure the tests pick up the latest code changes and are always up-to-date.

Copilot finished work on behalf of AndriySvyryd September 5, 2025 23:18
…with converters

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
…ode structure and remove method override

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
@Copilot Copilot AI requested a review from AndriySvyryd September 10, 2025 03:22
Copilot finished work on behalf of AndriySvyryd September 10, 2025 03:22
@AndriySvyryd AndriySvyryd changed the title SQLite: Make AUTOINCREMENT more first-class, fix value converter issues, add validation warnings, and support TPC mapping strategy [rc2] SQLite: Make AUTOINCREMENT first-class and fix false pending model changes warning for value converters Sep 10, 2025
@AndriySvyryd AndriySvyryd marked this pull request as ready for review September 10, 2025 07:11
@AndriySvyryd AndriySvyryd requested a review from a team as a code owner September 10, 2025 07:11
@AndriySvyryd AndriySvyryd requested a review from artl93 September 10, 2025 07:11
@AndriySvyryd AndriySvyryd removed the request for review from artl93 September 10, 2025 19:51
@SamMonoRT
Copy link
Member

If needed, please update any relevant documentation

@AndriySvyryd
Copy link
Member

@roji @cincuranet Please review the new public API

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed mostly new public API only, LGTM.

Note: if I understand correctly, after this PR it's still impossible to actually disable AUTOINCREMENT on primary keys, right? Either to use the default (recommended) SQLite ID generation algorithm (without AUTOINCREMENT), or to disable value generation altogether (which seems like it would require WITHOUT ROWIDS)?

/// <see href="https://aka.ms/efcore-docs-sqlite">Accessing SQLite databases with EF Core</see>
/// for more information and examples.
/// </remarks>
public class ConflictingValueGenerationStrategiesEventData : EventData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we really need a whole new heavy event + event data here? IIUC this is only for the case where the user misconfigures their model - we usually just do a simple warning (or even just throw), shouldn't we do this here? Is there a case where it makes sense for the user to actually configure a property with conflicting value generation strategies (and suppress this)?

(I can see that SQL Server has this too, but I'm trying to understand why we need it)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is mostly to avoid breaking changes.

Copy link
Member

@artl93 artl93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RC2 - as I understand it, this is the last chance to address a key customer issue with no opportunity for backporting.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements first-class support for SQLite AUTOINCREMENT through a formal value generation strategy system, addressing issues with value converters and false pending model changes warnings.

Key Changes:

  • Introduces SqliteValueGenerationStrategy enum with None and Autoincrement values
  • Replaces ad-hoc AUTOINCREMENT detection logic with a structured convention-based approach
  • Adds fluent API extension methods (UseAutoincrement()) for configuring AUTOINCREMENT
  • Implements proper annotation code generation for model snapshots

Reviewed Changes

Copilot reviewed 41 out of 42 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
SqliteValueGenerationStrategy.cs New enum defining SQLite-specific value generation strategies
SqlitePropertyExtensions.cs Extension methods for getting/setting value generation strategy on properties
SqlitePropertyBuilderExtensions.cs Fluent API methods for configuring AUTOINCREMENT
SqliteValueGenerationConvention.cs Convention that applies AUTOINCREMENT strategy based on property configuration
SqliteStoreGenerationConvention.cs Validation convention preventing conflicting value generation strategies
SqliteAnnotationCodeGenerator.cs Code generator for producing fluent API calls in model snapshots
Test files Comprehensive test coverage for new functionality and migration scenarios
Files not reviewed (1)
  • src/EFCore.Sqlite.Core/Properties/SqliteStrings.Designer.cs: Language not supported

@AndriySvyryd AndriySvyryd merged commit 327fe2c into release/10.0 Sep 18, 2025
7 checks passed
@AndriySvyryd AndriySvyryd deleted the copilot/fix-10228 branch September 18, 2025 18:55
@AndriySvyryd
Copy link
Member

AndriySvyryd commented Sep 18, 2025

Note: if I understand correctly, after this PR it's still impossible to actually disable AUTOINCREMENT on primary keys, right? Either to use the default (recommended) SQLite ID generation algorithm (without AUTOINCREMENT), or to disable value generation altogether (which seems like it would require WITHOUT ROWIDS)?

You can call .Metadata.SetValueGenerationStrategy(SqliteValueGenerationStrategy.None). We could also expose this in Fluent API if we can come up with a good name (perhaps UseAutoincrement(false))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SQLite: Make AUTOINCREMENT more first-class
6 participants