0

我有一个不错的 QC 测试工具,可以通过 VB 从现有设置中访问。该工具使我无需创建新类等即可对表进行强类型访问。但是,遗憾的是,其中一个表使用了 commalist 而不是子表。

这个commalist给我带来了问题。理论上,下面的代码应该拆分 row.commalist,然后告诉我给定的数字是否在其中。

我能够从 CommaListValues 位输出值 - 它是布尔值。我给它提供了给定的参数,编译器似乎很高兴。

为什么它在运行时不使用布尔值作为标准?我想我有一个心理障碍——我不经常使用 F#,但我非常想要——不幸的是,这些小问题会浪费时间。

任何人都可以帮忙吗?

按要求编辑。commalist 样本的典型值为:"234,132,554,6344,243,677"

module quality_control

open System
open System.Collections.Generic
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq

type dbschema = SqlDataConnection<"Data Source=SomeServer;Initial Catalog=SQLDB;User ID=sa;Password=######">

let db = dbschema.GetDataContext()

type QualityChecks(SingleIDToMatch) =
  let questionList ( q : string, SingleIDToMatch: string) = q.Split [| ','|] |> fun x -> x.Equals(SingleIDToMatch) 

  member x.MatchID=
      query{
       for row in db.SomeTableWithCommaListColumn do
       where (questionList(row.CommaListValue, System.Convert.ToString(SingleIDToMatch)))
       select row}

我收到以下错误:

System.ArgumentException 发生 HResult=-2147024809 消息=参数“值”的类型错误。应为“System.Func 2[System.Tuple2 [System.String,System.String],System.Boolean]”。实际的“System.Boolean”。Source=System.Data.Linq StackTrace:在 System.Data.Linq.SqlClient.SqlMethodCall.set_Object(SqlExpression 值)在 System.Data.Linq.SqlClient.SqlMethodCall..ctor(类型 clrType,ProviderType sqlType,MethodInfo 方法,SqlExpression obj , IEnumerable 1 args, Expression sourceExpression) at System.Data.Linq.SqlClient.SqlFactory.MethodCall(MethodInfo method, SqlExpression obj, SqlExpression[] args, Expression sourceExpression) at System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) at System.Data.Linq.SqlClient.QueryConverter.VisitWhere(Expression sequence, LambdaExpression predicate) at System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node) at System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations) at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery1.System.Collections.Generic.IEnumerable.GetEnumerator() 在删除项目详细信息 InnerException:

4

1 回答 1

3

类型提供程序尝试将查询表达式转换为 SQL,但它无法将questionList()调用转换为WHERE子句。简单的解决方案是更改MatchID()为如下所示:

member x.MatchID=
    let idString = singleIDToMatch.ToString()
    query {
        for row in db.SomeTableWithCommaListColumn do
        where (row.CommaListValue.EndsWith("," + idString)
            || row.CommaListValue.StartsWith(idString + ",")
            || row.CommaListValue.Contains("," + idString + ","))
        select row }

这将执行以下 SQL:

SELECT [t0].[CommaListValue]
FROM   [dbo].[SomeTableWithCommaListColumn] AS [t0]
WHERE  ([t0].[CommaListValue] LIKE @p0)
       OR ([t0].[CommaListValue] LIKE @p1)
       OR ([t0].[CommaListValue] LIKE @p2)

(参数包括适当的通配符,以提供与查询表达式中的 F# 代码等效的结果)


作品

如果需要组合多个WHERE子句,可以链接查询表达式,如下所示:

let withAtLeast10Characters (q : Linq.IQueryable<dbschema.ServiceTypes.SomeTableWithCommaListColumn>) =
    query {
        for row in q do
        where (row.CommaListValue.Length >= 10)
        select row }

let result = qualityChecks.MatchID |> withAtLeast10Characters

评估后,您将获得如下所示的 SQL:

SELECT [t0].[CommaListValue]
FROM   [dbo].[SomeTableWithCommaListColumn] AS [t0]
WHERE  (DATALENGTH([t0].[CommaListValue]) >= @p0)
       AND (([t0].[CommaListValue] LIKE @p1)
            OR ([t0].[CommaListValue] LIKE @p2)
            OR ([t0].[CommaListValue] LIKE @p3))
于 2013-09-05T18:44:43.440 回答