efcore icon indicating copy to clipboard operation
efcore copied to clipboard

SQLite: Make AUTOINCREMENT more first-class

Open smitpatel opened this issue 7 years ago • 9 comments

public partial class Preference
{
    public int PreferenceId { get; set; }
    public string Name { get; set; }
    public int? Value { get; set; }
    public string ValueString { get; set; }
}
modelBuilder.Entity<Preference>(entity =>
{
    entity.HasKey(e => e.PreferenceId);

    entity.Property(e => e.PreferenceId).HasColumnName("PreferenceID");

    entity.Property(e => e.Name).HasMaxLength(50);

    entity.Property(e => e.Value).HasDefaultValueSql(@"((0))");

    entity.Property(e => e.ValueString)
        .HasMaxLength(50)
        .HasDefaultValueSql(@"('')");
});

Generates following migration

migrationBuilder.CreateTable(
    name: "Preference",
    columns: table => new
    {
        PreferenceID = table.Column<int>(nullable: false)
            .Annotation("Sqlite:Autoincrement", true),
        Name = table.Column<string>(maxLength: 50, nullable: true),
        Value = table.Column<int>(nullable: true, defaultValueSql: "((0))")
            .Annotation("Sqlite:Autoincrement", true),
        ValueString = table.Column<string>(maxLength: 50, nullable: true, defaultValueSql: "('')")
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Preference", x => x.PreferenceID);
    });

This is because of ad-hoc logic here https://github.com/aspnet/EntityFrameworkCore/blob/b86eb8548a0deedc1199c3b4bc6b8632bd7824e3/src/EFCore.Sqlite.Core/Migrations/Internal/SqliteMigrationsAnnotationProvider.cs#L34-L38

And due to other hacks, later all annotations which are not on PK gets ignored. We should make autoincrement a first class for provider just like how SqlServer deals with identity.

@ErikEJ - SqlCE faces the same issue due to similar code and in SQL CE it tries to create multiple Identity columns failing at Update-Database command. You would also need to update SQL CE provider. (I found this after talking to customer on slack who hit issue on SQL CE)

smitpatel avatar Nov 06 '17 23:11 smitpatel

Assigning to @AndriySvyryd to give SQLite the same treatment (flag conventions, etc.) that SQL Server uses for this. @bricelam can help out on the Migrations part, if needed.

ajcvickers avatar Nov 09 '17 02:11 ajcvickers

@AndriySvyryd I added "propose-close" to make you feel at home with this one. :trollface:

ajcvickers avatar Nov 09 '17 02:11 ajcvickers

Is there a workaround for this? I want to test against an inmemory sqlite database since I have to use a relational database provider to run db commands for my asserts. (can't use inmemory option because of this requirement) unless there are alternatives

verstarr avatar Mar 18 '19 16:03 verstarr

@verstarr What issue are you having, specifically?

ajcvickers avatar Mar 20 '19 20:03 ajcvickers

~~Related: (mentioned in #15497)~~

~~There should be a way of configuring AUTOINCREMENT on one column of a composite primary key.~~

Scratch that, it's not possible in SQLite

bricelam avatar Apr 30 '19 17:04 bricelam

SqlServer:Identity is computed same way now. So only thing here to do is not generate auto increment for properties which are not autoincrement. Marking this as bug.

smitpatel avatar Aug 26 '20 16:08 smitpatel

Design proposal

  • Add model building API to configure AUTOINCREMENT. Parallel to UseIdentityColumn on SQL Server
modelBuilder.Entity<MyEntity>().Property(e => e.Id).UseAutoincrement();
modelBuilder.Entity<MyOtherEntity>().Property(e => e.Id).UseAutoincrement(false);
  • Add a convention to configure this by default on non-composite primary key properties with store type INTEGER

  • Add validation to make sure it's not configured on non-INTEGER, composite, or non-primary-key properties

  • Honor the configuration in Migrations

  • Ensure RevEng does the right thing

bricelam avatar Aug 26 '20 19:08 bricelam

SqlServer:Identity is computed same way

Does it honor the SqlServer:ValueGenerationStrategy annotation on the model? Or is there a bug...

bricelam avatar Aug 26 '20 19:08 bricelam

It utilizes SqlServerValueGenerationStrategy.

smitpatel avatar Aug 26 '20 19:08 smitpatel

Also not in v 8? =)

voroninp avatar Aug 23 '23 20:08 voroninp

@voroninp as always, we prioritize features based on user interest (among other things), and this issue has received only 2 votes.

roji avatar Aug 24 '23 06:08 roji

@roji , I keep questioning myself how come I always bump into edge cases while others are happy with what they have =D

voroninp avatar Aug 24 '23 06:08 voroninp

To be fair, at least four other people have ran into issues because of the current design. Unfortunately they, like @voroninp, haven't upvoted this issue. Remember to vote if you want to see things fixed. With 1.9k issues it really can make years of difference.

bricelam avatar Aug 24 '23 16:08 bricelam

@bricelam, I'd 100% upvote, if I faced the issue before, but it happened on the 2nd day after I used sqlite provider for the first time. =)

voroninp avatar Aug 25 '23 14:08 voroninp

4th Anniversary coming in two weeks or so and I just stumbled upon this while using SQLite for in-memory db for unit testing sheesh.

Upvoted, maybe one day.

HalinSky avatar Nov 28 '23 09:11 HalinSky

+1 This one is important. The current implementation is causing a lot of issues with value converters.

bricelam avatar Nov 28 '23 22:11 bricelam