规范 - 在泛型中查询条目会导致类型不匹配编译错误

Norm - Querying entries within generics causes type mismatch compilation error

我用 nim 编程语言编写了一个 Web 应用程序,并使用 norm 作为我的 ORM。

我遵循标准的存储库模式,这意味着您已经与给定的 URL 控制器相关联,该控制器调用包含关于数据库上应该发生的事情的业务逻辑的服务,它调用存储库来执行实际查询.

我有一个通用存储库,可以为我执行各种非常重复的查询。例如,以下查询获取与具有特定名称的“活动”相关的所有条目的列表:

import norm/[model, sqlite]
import <path to the file with the definitions of the used Model and newModel>


proc getCampaignList*[M: Model](connection: DbConn, campaignName: string, modelType: typedesc[M]): seq[M] =
    ##[ Retrieves all rows/entries for a campaign with the given name and 
    returns them as Model M. 
    
    ``campaignName`` must be exactly equal to the name of the targetted campaign,
    the comparison is case-sensitive.]##
    mixin newModel

    var entries: seq[M] = @[]
    entries.add(newModel(M))
    
    connection.select(entries, "campaign_id.name = ?", campaignName)

    result = entries

如果我直接调用 proc,这很好用。然而,我也一直在编写为我构建控制器进程的通用进程,因为我的应用程序 非常 CRUD 繁重,因此非常重复。所以我有一个 genericService 等等。

在这几层泛型中使用时,过程神秘地中断:

type mismatch: got <DbConn, seq[DiaryEntryRead], string, DbValue>
but expected one of:
...
<Unnecessary examples>
...
proc select[T: Model](dbConn; objs: var seq[T]; cond: string;
                      params: varargs[DbValue, dbValue])
  first type mismatch at position: 4
  required type for params: varargs[DbValue]
  but expression 'dbValue(campaignName)' is of type: DbValue

expression: select(connection, entries, "campaign_id.name = ?", dbValue(campaignName))

我不确定为什么这在之前工作得很好的时候突然发生了。我的问题可能是什么?

问题似乎出在 nim 泛型与将类型正确转换为可变参数之间的交互中(感谢来自 nim 的 discord 服务器的“Solitude”和“Rika”的帮助!)。关于为什么会发生这种情况,我还没有深入研究,但至少它是可以修复的。

你把4位以后的参数丢进去的参数直接转成DbValue塞进数组或者seq就可以了。下面我解决了这个问题并“万无一失”了过程(我使用了一个数组,因为当参数数量是静态的并且你提前知道它时为什么要使用seq):

proc getCampaignList*[M: Model](connection: MyDbConn, campaignName: string, modelType: typedesc[M]): seq[M] =
    ##[ Retrieves all rows/entries of a campaign with the given name and 
    returns them as Model M. 
    
    ``campaignName`` must be exactly equal to the name of the targetted campaign,
    the comparison is case-sensitive.]##
    mixin newModel

    var entries: seq[M] = @[]
    entries.add(newModel(M))
    
    let queryParams: array[1, DbValue] = [campaignName.dbValue()]
    connection.select(entries, "campaign_id.name = ?", queryParams)

    result = entries