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

时间:2018-01-11 19:29:25

标签: swift sqlite fluent vapor

我正在使用Vapor API,在使用FluentProvider时,我正在尝试根据Users中的Users模型创建App/Models/Users.swift表:

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提供程序相关联。我想使用String格式的UUID作为此表的主键。

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

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.

如果我理解正确,它只接受一个名为&#34; id&#34;的ID列,显然只能使用builder.id()方法生成,该方法只分配一个自动递增的整数到ID。

所以我的问题是:

  1. 是否可以使用特定列作为主键/标识符 列,如果有,怎么做?

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

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:0)

我在我的Vapor项目中使用UUID没有问题,也没有必要在准备中编写自定义代码。

您是否尝试在fluent.json中设置idType?

"idType": "uuid"

请注意我指的是Vapor 2.4