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
);
【问题讨论】:
唯一需要的修改是从int
到integer
。
【参考方案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 上使用'的主要内容,如果未能解决你的问题,请参考以下文章