sql - F# 查询异常, "unrecognized method call value"

标签 sql .net exception f# pervasive

问:以下异常是什么意思?

System.Exception: 'unrecognised method call value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable`1[FSharp.Data.Sql.Common.SqlEntity]).GroupJoin(value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable`1[FSharp.Data.Sql.Common.SqlEntity]), arClientRow => arClientRow.GetColumn("CLIENT_ID"), dsItemRow => dsItemRow.GetColumn("CLIENT_ID"), (arClientRow, dsItemGroup) => new AnonymousObject`2(Item1 = arClientRow, Item2 = dsItemGroup.DefaultIfEmpty()))'

我正在尝试使用 SqlDataProvider 和 ODBC 连接将 Pervasive SQL 查询转换为 F# 查询,一点一点地慢慢构建。我在以下查询中遇到异常,其中有一个有点神秘的异常。

let Q2KQuery = query {
    for arClientRow in Q2KDb.Dbo.ArClient do
    leftOuterJoin dsItemRow in Q2KDb.Dbo.DsItem 
        on (arClientRow.ClientId = dsItemRow.ClientId) 
        into dsItemGroup
    select (arClientRow, dsItemGroup) (*select statement simplified here for demonstration purposes*)
}

printfn "%i" (Seq.length Q2KQuery)

当执行printfn语句并实际计算表达式时,会遇到异常:

System.Exception: 'unrecognised method call value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable`1[FSharp.Data.Sql.Common.SqlEntity]).GroupJoin(value(FSharp.Data.Sql.Runtime.QueryImplementation+SqlQueryable`1[FSharp.Data.Sql.Common.SqlEntity]), arClientRow => arClientRow.GetColumn("CLIENT_ID"), dsItemRow => dsItemRow.GetColumn("CLIENT_ID"), (arClientRow, dsItemGroup) => new AnonymousObject`2(Item1 = arClientRow, Item2 = dsItemGroup.DefaultIfEmpty()))'

这是一个更大的查询的一部分,该查询在执行时具有完全相同的异常:

let Q2KQuery = query {
    for arClientRow in Q2KDb.Dbo.ArClient do
    leftOuterJoin dsItemRow in Q2KDb.Dbo.DsItem 
        on (arClientRow.ClientId = dsItemRow.ClientId) 
        into dsItemGroup
    for dsItemRow in dsItemGroup do
    leftOuterJoin dsWhseInvHeaderRow in Q2KDb.Dbo.DsWhseInvHeader
        on ((dsItemRow.ClientId, dsItemRow.ItemId) = (dsWhseInvHeaderRow.ClientId, dsWhseInvHeaderRow.ItemId))
        into dsWhseInvHeaderGroup
    for dsWhseInvHeaderRow in dsWhseInvHeaderGroup do
    where (
        dsItemRow.ObsoleteFlg <> "Y"
        && arClientRow.IsInactive <> "Y"
        && dsWhseInvHeaderRow.WhseId = "B1"
        && dsItemRow.InvunitQty = 1
    )
    select (arClientRow, dsItemRow, dsWhseInvHeaderRow) (*select statement simplified here for demonstration purposes*)
}

仅供引用,转换此 F# 查询的 SQL 查询如下(SELECT 语句不如抛出 F# 异常的 JOIN 子句那么重要):

SELECT
-- LOTS of selects here... --
-- ... --
----- the important part of the F# queries begin here -----
FROM 
    ArClient
    LEFT JOIN DsItem 
    ON ArClient.CLIENT_ID = DsItem.CLIENT_ID
    LEFT JOIN DsWhse_Inv_Header 
    ON (DsItem.CLIENT_ID = DsWhse_Inv_Header.CLIENT_ID)
    AND (DsItem.ITEM_ID = DsWhse_Inv_Header.ITEM_ID)
WHERE (
    ((DsItem.OBSOLETE_FLG) <> 'Y')
    AND ((ArClient.IS_INACTIVE) <> 'Y')
    AND ((DsWhse_Inv_Header.WHSE_ID) = 'B1')
    AND ((DsItem.INVUNIT_QTY) = 1)
    )
ORDER BY
    CONCAT(LEFT(DsItem.CLIENT_ID, 4), RTRIM(LTRIM(DsItem.ITEM_ID)));

最佳答案

在阅读了一些 SO 答案和 GitHub 问题(下面链接)后,似乎目前不支持以我正在执行的方式对这种 SQL 数据库进行的确切操作(也许?至少在我看来)理解我读到的内容),尽管显然 left 加入 query表达式可以使用 !!运算符(operator)——但到目前为止我还没有成功。

已经但是使用相同的 query 发现了以下笨拙的解决方法我一直在使用的表达式是通过将数据转换为 List 来强制将数据读入内存。 (或 Array 等)首先:

let ArClient = Seq.toList <| query {
    for row in Q2KDb.Dbo.ArClient do
    where (row.IsInactive <> "Y")
    select row
}

let DsItem = Seq.toList <| query {
    for row in Q2KDb.Dbo.DsItem do
    where (row.ObsoleteFlg <> "Y" && row.InvunitQty = 1)
    select row
}

let DsWhseInvHeader = Seq.toList <| query {
    for row in Q2KDb.Dbo.DsWhseInvHeader do
    where (row.WhseId = "B1")
    select row
}

然后可以在原来的query中使用表达变化最小。

let results = Seq.toList <| query {
    for arClientRow in ArClient do
    leftOuterJoin dsItemRow in DsItem
        on (arClientRow.ClientId = dsItemRow.ClientId) 
        into dsItemGroup
    for dsItemRow in dsItemGroup do
    leftOuterJoin dsWhseInvHeaderRow in DsWhseInvHeader
        on ((dsItemRow.ClientId, dsItemRow.ItemId) = (dsWhseInvHeaderRow.ClientId, dsWhseInvHeaderRow.ItemId))
        into dsWhseInvHeaderGroup
    for dsWhseInvHeaderRow in dsWhseInvHeaderGroup do
    select (arClientRow (*etc etc*))

这当然是非常低效的(读取 DsItem 的 62k+ 行使用大约 500MB+ 的内存,并且需要 30+ 秒的时间来读取),但它确实有效......


链接:

SO: F# groupBy - System.Exception : unrecognized method call

GitHub: "unrecognised method call value" on a left outer join #588

GitHub: Ordering of joins can cause runtime exception with (!!) #614

GitHub: leftOuterJoin causing "unrecognized method call" with Postgresql #235

关于sql - F# 查询异常, "unrecognized method call value",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64584228/

相关文章:

c# - 中止使用 Delegate.BeginInvoke 启动的线程

c++ - 在 C++ 中哪些操作不能抛出异常?

asp.net - 想要构建一个在线网络邮件脚本

sql - 更新表变量

.net - NuGet 自动包还原不适用于 MSBuild

ruby-on-rails - 在 Rails 中处理异常和错误的最佳策略是什么?

java - 是Throwable类的printStackTrace(),异步

多个表上的 SQL 求和函数和计数函数会产生相乘的值

java.sql.SQLException : no such column: after accepting sql query

.net - 来自 bash,要学习什么 Windows 脚本语言?