如何在 FluentProvider for Vapor 中使用字符串化的 UUID 作为主键 - Swift

How to use a stringified UUID as Primary Key in FluentProvider for Vapor - Swift

我正在使用 Vapor API,在使用 FluentProvider 时,我正在尝试基于 Users 中的 Users 模型创建 Users table 16=]:

final class Users: Model {
    let storage = Storage()

    // Properties
    let UserUUID:  String
    let FirstName: String
    let LastName:  String
    let EMail:     String
    let Password:  String

    // Initializer
    init( userUUID:  String,
          firstName: String, lastName: String, 
          email:     String, password: String ) 
    {
        self.UserUUID  = userUUID
        self.FirstName = firstName
        self.LastName  = lastName
        self.EMail     = email
        self.Password  = password
    }

    init(row: Row) throws {
        UserUUID  = try row.get("UserUUID" )
        FirstName = try row.get("FirstName")
        LastName  = try row.get("LastName" )
        EMail     = try row.get("EMail"    )
        Password  = try row.get("Password" )
    }

    func makeRow() throws -> Row {
        var row = Row()

        try row.set("UserUUID",  UserUUID )
        try row.set("FirstName", FirstName)
        try row.set("LastName",  LastName )
        try row.set("EMail",     EMail    )
        try row.set("Password",  Password )

        return row
    }
}

这默认与 SQLite 提供程序相关联。我想使用字符串格式的 UUID 作为此 table.

的主键

我的问题是,在为这个模型编写准备时,它只希望将主键命名为 "id",用 builder.id() 创建。如果我尝试改为创建自定义列并将其用作主要 Key/Identifier,则会引发错误。准备代码如下:

extension Users: Preparation {
    static func prepare(_ database: Database) throws {
        try database.create(self) { builder in

            /* builder.id()    <- intentionally omitted. */
            builder.custom( // <- Attempted in place of builder.id()
                "UserUUID",  
                 type:"VARCHAR(255) PRIMARY KEY", 
                 optional: false, 
                 unique: true
            ) 
            builder.string("FirstName", optional: false, unique: false)
            builder.string("LastName",  optional: false, unique: false)
            builder.string("EMail",     optional: false, unique: true)
            builder.string("Password",  optional: false, unique: false)
        }
    }

    static func revert(_ database: Database) throws {
        try database.delete(self)
    }
}

从API调用关联路由时产生的错误:

POST /service/users/new
[SQLite.StatusError: error("table userss has no column named id")]
Conform 'SQLite.StatusError' to Debugging.Debuggable to provide more 
debug information.

如果我理解正确,它只会接受一个名为 "id" 的 ID 列,显然只能使用 builder.id() 方法生成,该方法只会将一个自动递增的整数分配给身份证。

所以我的问题是:

  1. 是否可以使用特定列作为主要列Key/Identifier 专栏,如果是,怎么做?

  2. 会将 "UserUUID" 重命名为 "id" 但保留其余部分 同样的属性也可以作为解决方案吗?

看起来 Fluent 知道如何通过在 Entity 上使用静态变量来创建 ID,这是您的 User 模型所遵循的协议。具体来说,您似乎需要覆盖以下两个变量:

final class Users: Model {
    static var idKey: String {
        return "UserUUID"
    }
    static var idType: IdentifierType {
        return .uuid
    }
}

现在,如果您取消注释 builder.id() 行,则应该会正确创建 ID。

我在我的 Vapor 项目上使用 UUID 没有问题,并且不必在准备过程中编写自定义代码。

您尝试过在 fluent.json 中设置 idType 吗?

"idType": "uuid"

请注意我指的是 Vapor 2.4