F# 查询异常,"unrecognized method call value"
F# Query Exception, "unrecognized method call value"
问:下面的异常是什么意思?
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()))'
我正在尝试将 Pervasive SQL 查询转换为使用 SqlDataProvider
和 ODBC 连接的 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 数据库进行确切的操作目前(也许吧?至少据我所知是这样),尽管 !!
运算符显然可以在 query
表达式中加入左连接——但到目前为止我还没有成功.
我 有 但是发现以下笨拙的解决方法使用我一直使用的相同 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+ 秒来读取),但它 实际上 工作...
链接:
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
问:下面的异常是什么意思?
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()))'
我正在尝试将 Pervasive SQL 查询转换为使用 SqlDataProvider
和 ODBC 连接的 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 数据库进行确切的操作目前(也许吧?至少据我所知是这样),尽管 !!
运算符显然可以在 query
表达式中加入左连接——但到目前为止我还没有成功.
我 有 但是发现以下笨拙的解决方法使用我一直使用的相同 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+ 秒来读取),但它 实际上 工作...
链接:
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