如何修复使用自定义工作流构建器的计算表达式生成的这些错误



从 MSDN 文档中,我了解到如果实现了 Run,它将在计算表达式结束时自动调用。它说:

builder.Run(builder.Delay(fun () -> {| cexpr |}))

将为计算表达式生成。如果未在工作流构建器中定义运行和/或延迟,则将省略它们。我期望我的 ReaderBuilder 在自动调用 Run 时返回 MyItem 对象列表。所以我不明白为什么我会收到类型不匹配错误。错误是由我在此处的代码清单末尾的 ProcedureBuilder foo 中的 return 语句生成的。有人可以解释一下我对工作流构建器的误解以及我不正确地实现什么吗?

我收到以下错误:

类型"列表"与类型"ReaderBuilder"不兼容

类型约束不匹配。类型"列表"与类型"ReaderBuilder"不兼容 类型"列表"与类型"ReaderBuilder"不兼容

open System
open System.Data
open System.Data.Common
open System.Configuration
let config = ConfigurationManager.ConnectionStrings.Item("db")
let factory = DbProviderFactories.GetFactory(config.ProviderName)
type Direction =
    | In
    | Out
    | Ref
    | Return
type dbType =
    | Int32
    | String of int

type ReaderBuilder(cmd) =
    let mutable items = []
    member x.Foo = 2
    member x.YieldFrom item =
        items <- item::items
        item
    member x.Run item =
        items

type ProcBuilder(procedureName:string) =
    let name = procedureName
    let mutable parameters = []
    let mutable cmd:DbCommand = null
    let mutable data = []
    member x.Command with get() = cmd
    member x.CreateCommand() =
        factory.CreateCommand()
    member x.AddParameter(p:string*dbType*Direction) =
        parameters <- p::parameters
    member x.Bind(v,f) =
        f v
    member x.Reader = ReaderBuilder(cmd)
    member x.Return(rBuilder:ReaderBuilder) =
        data

let (?<-) (builder:ProcBuilder) (prop:string) (value:'t) =
    builder.Command.Parameters.[prop].Value <- value

type MyItem() =
    let mutable _a = 0
    let mutable _b = String.Empty
    let mutable _c = DateTime.Now
    member x.a
        with get() = _a
        and set n = _a <- n
    member x.b
        with get() = _b
        and set n  = _b <- n
    member x.c
        with get() = _c
        and set n = _c <- n

let proc name = ProcBuilder(name)
let (%) (builder:ProcBuilder) (p:string*dbType*Direction) =
    builder.AddParameter(p)
    builder
let (?) (r:DbDataReader) (s:string) = r.GetOrdinal(s)
let foo x y = 
    let foo = proc "foo" % ("x", Int32, In) % ("y", String(15), In)
    foo?x <- x
    foo?y <- y
    foo {
        do! foo?x <- x
        do! foo?y <- y
        return foo.Reader {
            let item = MyItem()
            item.a <- r.GetInt32("a")
            item.b <- r.GetString("b")
            item.c <- r.GetDateTime("c")
            yield! item
        }
    }
示例中的

问题是foo.Reader { ... }块具有返回类型MyItem list(因为这是ReaderBuilder类型的Run成员返回的内容)。但是,ProcBuilderReturn成员需要类型 ReaderBuilder 的参数。

ReaderBuilderdata字段将始终为空列表,因此这也是可疑的。我想你可能想改变ProcBuilder Return,改MyItem list论点。

但是,我认为使用自定义计算生成器进行数据库访问并不能真正为您带来太大优势。从某种意义上说,你不是在创建"非标准计算"。相反,您可能只需要一个很好的语法来调用命令和读取数据。即使没有计算构建器,使用动态运算符也可以使它变得非常优雅 - 我前段时间写了一篇关于这个的文章。

相关内容

  • 没有找到相关文章

最新更新