SQL 具有 ROP 的类型提供程序 - F#

SQL Type Providers with ROP - F#

我正在尝试使用面向铁路的编程原则http://fsharpforfunandprofit.com/rop/ and this http://indiedevspot.azurewebsites.net/2015/01/20/two-track-coding-rop-for-dummies-part-2/作为参考

我已经为大部分代码库成功实现了这一点,除了现在我们要将项目放入 SQL 并希望使用 ROP 来验证这些类型。典型的模式是

图一:

let createSomething a b c = {A = a; B = b; C = c}
let createValidSomething so = 
    createSomething
    <!> validateFunction1 so.param1
    <*> validateFunction2 so.param2
    <*> ...so forth and so on

你会注意到 createSomething 是一个 returns 记录类型实例化 a -> b -> c -> a' -> b' -> c' 的函数 SQL 类型提供者 return 可变类型(非记录)。让我们看看我尝试构建一个类似的 createSomething 函数

图二:

    let createSQS(a, b, c, d, e, f, g) =
    let sqs = context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)
    sqs

此时,我们知道这已经行不通了,我们有 a->b->c->d->e->f->g->context.[dbo].[Something].Entity

我知道我可以有一个中间记录类型并遵循 ROP 原则,在 success/failure 上匹配,然后从已经验证的对象中创建我的对象。但这似乎不是太多步骤吗?

有人知道一个好的模式吗?理想情况下,我们可以使用类似于图 1 的函数来生成与类型提供程序兼容的记录类型。

我乐于尝试并在 Skype 上闲逛 :)。

你的函数 createSQS 不应该像这样更好吗:

let createSQS a b c d e f g =
    context.``[dbo].[Something]``.Create(a, b, c, d, e, f, g)

这个将具有 a->b->c->d->e->f->g->context.[dbo].[Something].Entity

所需的签名

所以我们在开发会议上得出了一个答案,并决定我们实际上想要在其自己的函数中执行每个部分。对于内部绑定,我们发明了自己的运算符;类似于加号 (&&&)(我将在我的网站 www.indiedevspot.com 上写博客)并且在顶层我们 运行 具有正常绑定。

我们的顶级代码如下所示:

[<HttpPost>]
x.member Add(sa:Something) =
           sa|>ValidateSomething
           >>= converttoSSA
           >>= persistSSA

由于验证、转换和持久性的独立可测试性,我们决定将关注点分开。该理论认为,如果函数组合由保证 运行 可以工作的函数组成,那么它本身就可以保证 运行 可以工作(或者有更好的机会)。

如果我们采用提议的方法(我们尚未解决),我们将混合创建、验证和转换的问题。这也将最终创建一个额外的记录类型,即 un-necessary.