SqLite为其组合键之一自动递增

时间:2018-12-05 19:40:36

标签: c# .net entity-framework sqlite testing

SqLite Composite Keys

以下列在SQL Server IDENTITY(1,1)中设置为自动递增,我希望在SqLite上具有类似的行为:租户。租户ID ,项目。项目ID ,和信用。信用ID 。尽管SqLite中有AUTOINCREMENT,并且我已经尝试过,但是它仅适用于只有1个主键的表。我已经尝试了以下测试:

顺便说一句,我使用Microsoft.EntityFrameworkCore.Sqlite 2.1.4进行测试

为这些设置为自动递增的列明确分配值:

  1. Tenant.TenantID

    a。 -99 :保存后仍为-99

    b。 0 :保存后变为1

    c。 99 :保存后仍为99

  2. 对于Project.ProjectIDCredits.CreditsID

    a。将更改保存到DbContext后,-99和99值保持不变。但是我不想显式地分配这些值,因为我的DbContext有很多测试数据。

    b。分配显式值0会引发此错误:Microsoft.Data.Sqlite.SqliteException : SQLite Error 19: 'NOT NULL constraint failed: Credits.CreditsID'.

我真的很感谢能帮助我解决这个问题的人。几天来,这困扰着我。

1 个答案:

答案 0 :(得分:0)

使用SQLite时,您可能不想使用AUTOINCREMENT,这实际上并没有将列设置为递增,而是设置了一个约束,即如果未明确设置,则该值必须大于分配的值。

如果未明确设置值,则使用INTEGER PRIMARY KEY简单定义一列即可将列递增。注意每个表只能有一个这样的列。

  • 请注意,SQLite不保证递增1,而是保证唯一的标识符,该标识符是整数,甚至可以更少(仅在ID为9223372036854775807的情况下分配)。SQLite Autoincrement。在这种情况下,使用AUTOINCREMENT将失败并显示SQLIte Full异常,而在没有AUTOINCREMENT的情况下,SQLite将尝试查找未使用的ID。

查看您的图表,我相信Credits表不需要TennantID,因为可以通过引用Tennant的项目获得它。

忽略构成关系的列(也添加可选的外键约束,以强制执行参照完整性),然后相信您可以使用以下类似的方法:-

DROP TABLE IF EXISTS credits;
DROP TABLE IF EXISTS project;
DROP TABLE IF EXISTS tennant;
CREATE TABLE IF NOT EXISTS tennant (tennant_id INTEGER PRIMARY KEY, Name TEXT, other_columns);
CREATE TABLE IF NOT EXISTS project (project_id INTEGER PRIMARY KEY, tennant_reference REFERENCES tennant(tennant_id), Title);
CREATE TABLE IF NOT EXISTS credits (credit_id INTEGER PRIMARY KEY, project_reference INTEGER REFERENCES project(project_id), other_columns TEXT);
CREATE TABLE IF NOT EXISTS creidts (credit_id INTEGER PRIMARY KEY, project_reference INTEGER, other_columns);
INSERT INTO tennant VALUES(1,'Fred','other data'); -- Explicit ID 1
INSERT INTO tennant (Name,other_columns) VALUES('Mary','Mary''s other data'),('Anne','Anne''s other data'); -- Implicit ID 's (2 and 3 most likely)
INSERT INTO project VALUES (99,1,'Project001 for Fred'); --  Explicit Project ID 99 - tennant 1 = Fred
INSERT INTO project (tennant_reference,Title) VALUES(1,'Project002 for Fred'),(2,'Project003 for Mary'),(3,'Project004 for Anne'); -- 3 implicit project id's 100,101 and 102 (most likely)

-- Result 1
SELECT * FROM project JOIN tennant ON tennant_reference = tennant.tennant_id;

INSERT INTO credits VALUES(199,99,'Other credit columns'); -- Explicit credit ID of 199 for Project001 (tennant implied) 
INSERT INTO credits VALUES(0,99,'Other credit colums credit_id = 0'); -- Explicit credit ID of 0 for Project002
INSERT INTO credits (project_reference,other_columns) VALUES (100,'for Project002'),(100,'another for Project002'),(102,'for Project004');

SELECT * FROM credits JOIN project ON project_reference = project_id JOIN tennant ON tennant_reference = tennant_id;
  • 这会删除所有现有表以简化测试。
  • 然后创建3个表。
  • 将行显式和隐式地(推荐的方式)插入Tennant表中,然后插入Project表中(请注意,由于外键约束,引用不存在的Tennant的行不能插入Project表中)
  • 然后列出了项目以及相关的租户详细信息(请参见结果)
  • 然后使用显式和隐式信用ID将行插入“信用”表(请注意,显式定义为199,然后为0)。
  • 如您所见,自动生成ID时,它们通常比迄今为止使用的最大值大1。

结果

第一个查询(带有相关Tennant的项目)

enter image description here

具有相关项目和基础相关Tennant的第二查询积分

enter image description here