Efcore: SQLite: Make AUTOINCREMENT more first-class

Created on 7 Nov 2017  路  9Comments  路  Source: dotnet/efcore

```C#
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(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
```C#
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)

area-model-building area-sqlite consider-for-current-release punted-for-2.1 punted-for-3.0 type-enhancement

All 9 comments

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.

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

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 What issue are you having, specifically?

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

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.

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

SqlServer:Identity is computed same way

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

It utilizes SqlServerValueGenerationStrategy.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

satyajit-behera picture satyajit-behera  路  275Comments

matteocontrini picture matteocontrini  路  88Comments

bricelam picture bricelam  路  74Comments

dgxhubbard picture dgxhubbard  路  97Comments

0xdeafcafe picture 0xdeafcafe  路  189Comments