Microsoft.Data.Sqlite.SqliteException SQLite 错误 1:'AUTOINCREMENT 只允许在 INTEGER PRIMARY KEY 上使用'

Posted

技术标签:

【中文标题】Microsoft.Data.Sqlite.SqliteException SQLite 错误 1:\'AUTOINCREMENT 只允许在 INTEGER PRIMARY KEY 上使用\'【英文标题】:Microsoft.Data.Sqlite.SqliteException SQLite Error 1: 'AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY'Microsoft.Data.Sqlite.SqliteException SQLite 错误 1:'AUTOINCREMENT 只允许在 INTEGER PRIMARY KEY 上使用' 【发布时间】:2021-12-05 19:28:48 【问题描述】:

我有一个 EF Core DbContext(继承自 IdentityDbContext)和一堆迁移。在我的网络应用中一切正常。

我有一堆单元测试,它们使用 Microsoft.EntityFrameworkCore.Sqlite 针对 Sqlite 内存数据库启动 DbContext。

当我运行单元测试时,我收到以下错误:

Microsoft.Data.Sqlite.SqliteException SQLite 错误 1:'AUTOINCREMENT 只允许在 INTEGER PRIMARY KEY 上使用'。

我怎样才能知道这个错误是在哪里引起的?

script-database -Idempotent 不会产生任何AUTOINCREMENT 的实例,尽管我认为它使用的是 T-SQL 方言,而不是 Sqlite?

我怎样才能找到这个问题的根本原因?

更新

好的,所以我将调试器设置为在引发 Sqlite 异常时中断,然后为 Microsoft.Data.Sqlite 加载符号,在SqliteCommand.PrepareAndEnumerateStatements() 中我可以看到_commandText 字段具有以下值,即由 EntityFramework 从迁移中生成:

CREATE TABLE "ef_temp_AspNetRoleClaims" (
    "Id" int NOT NULL CONSTRAINT "PK_AspNetRoleClaims" PRIMARY KEY AUTOINCREMENT,
    "ClaimType" nvarchar(1000) NULL,
    "ClaimValue" nvarchar(1000) NULL,
    "RoleId" uniqueidentifier NOT NULL,
    CONSTRAINT "FK_AspNetRoleClaims_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE
);

【问题讨论】:

唯一需要的修改是从intinteger 【参考方案1】:

我怎样才能知道这个错误是在哪里引起的?

这将是创建表的时候。您需要更改 CREATE SQL;要使用 AUTOINCREMENT,您必须使用 INTEGER 而不是 INT。即INTEGER PRIMARY KEY AUTOINCREMENT

所以:-

CREATE TABLE "ef_temp_AspNetRoleClaims" (
    "Id" integer NOT NULL CONSTRAINT "PK_AspNetRoleClaims" PRIMARY KEY AUTOINCREMENT,
    "ClaimType" nvarchar(1000) NULL,
    "ClaimValue" nvarchar(1000) NULL,
    "RoleId" uniqueidentifier NOT NULL,
    CONSTRAINT "FK_AspNetRoleClaims_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE
)

;

根据:-

除了下面提到的一个例外,如果 rowid 表的主键由单个列组成,并且该列的声明类型为“INTEGER”(大小写任意混合),则该列将成为行标识。这样的列通常称为“整数主键”。如果声明的类型名称恰好是“INTEGER”,则 PRIMARY KEY 列仅成为整数主键。其他整数类型名称,如“INT”或“BIGINT”或“SHORT INTEGER”或“UNSIGNED INTEGER”会导致主键列表现为具有整数亲和性和唯一索引的普通表列,而不是 rowid 的别名。

CREATE TABLE - 5. ROWIDs and the INTEGER PRIMARY KEY 和 AUTOINCREMENT

即AUTOINCREMENT只能应用于rowid的别名。

您可能希望考虑第一段而不使用 AUTOINCREMENT 只需使用 INTEGER PRIMARY KEY :-

AUTOINCREMENT 关键字会带来额外的 CPU、内存、磁盘空间和磁盘 I/O 开销,如果不是严格需要,应避免使用。通常不需要。

即 AUTOINCREMENT 不会自动递增,而是一个规则/约束,分配的值将始终高于(不保证它高 1,但通常高 1)比任何已分配的值。

它的效率较低,因为它需要一个额外的表 sqlite_seqeunce,其中存储了该表的最高分配值。在确定要分配的新值时,使用此值或实际表中的值中的较高者。

如果没有 AUTOINCREMENT,如果没有指定值,那么将仅使用表中的最大值来确定该值。此确定,如果已达到最高允许值 (9223372036854775807),则尝试使用较低的空闲/未使用值(使用 AUTOINCREMENT 会导致 SQLite FULL 错误,而不是使用较低的空闲/未使用值)。

【讨论】:

感谢您的广泛回复。我已经更新了我的问题,因为我意识到我遗漏了一条关键信息......查询是由 EF 迁移系统生成的,但您的详细信息至少让我朝着正确的方向前进,为什么 EF 会生成不正确的 Sqlite SQL? @GregB 你有.HasColumnType("int")吗?如果是这样,请尝试将其注释掉。也许你可以使用.HasColumnType("integer") ?。但是,我从未使用过 EF。

以上是关于Microsoft.Data.Sqlite.SqliteException SQLite 错误 1:'AUTOINCREMENT 只允许在 INTEGER PRIMARY KEY 上使用'的主要内容,如果未能解决你的问题,请参考以下文章