【问题标题】:F# Power Pack Linq IssueF# Power Pack Linq 问题
【发布时间】:2011-09-20 01:21:34
【问题描述】:

我有一个简单的函数,它利用 F# 电源包将引用转换为 linq 表达式。功能是:

let toLinq (exp : Expr<'a -> 'b>) =
    let linq = exp.ToLinqExpression()
    let call = linq :?> MethodCallExpression
    let lambda = call.Arguments.[0] :?> LambdaExpression
    Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)

我使用这个函数来创建一个 C# 库使用的表达式,该库使用 linq to sql 来查询数据库。例如,我可能会构建如下表达式:

    let test = toLinq (<@fun u -> u.FirstName = "Bob"@> : Expr<Account->bool>)

并将其传递给类似的方法:

public IEnumerable<T> Find(Expression<Func<T, bool> predicate)
{
        var result = Table.OfType<T>();         
        result = result.Where(predicate)                                    
        var resultArray = result.ToArray();            
        return resultArray;
}

这与电源组 1.9.9.9 版本中的设计相同。但是,它不再适用于最新版本的电源组。我收到的错误是Method 'Boolean GenericEqualityIntrinsic[String](System.String, System.String)' has no supported translation to SQL.

我查看了电源组的更改,似乎使用新版本构建的 linq 表达式使用 GenericEqualityIntrinsic 将属性值与常量进行比较,而在版本 1.9.9.9 中它使用了String.op_Equality 用于比较。

这是对问题的正确理解吗?如何利用新版本的电源包将引号转换为可以被使用 linq to sql 的 c# 库使用的 linq 表达式?

【问题讨论】:

    标签: linq f# powerpack


    【解决方案1】:

    显式调用

    System.String.op_Equality(s1,s2)
    

    工作?

    【讨论】:

    • 是的。例如,如果我手动构建表达式:let ManualExpression() = let pe = Expression.Parameter( Operators.typedefof&lt;Account&gt;, "u") let ce = Expression.Constant("Bob", typedefof&lt;System.String&gt;) let e = Expression.Equal(Expression.PropertyOrField(pe, "Firstname"), ce) let predicate = Expression.Lambda&lt;Func&lt;'a, 'b&gt;&gt;(e, [|pe|]) predicate System.String.op_Equality 使用并没有问题。
    • 另外,如果我将电源组中 Linq.fs 的第 523 行修改回版本 1.9.9.9 中的内容,我同样没有问题。但是,据我所知,这只会解决相等比较的问题,我仍然会遇到 > 的问题。
    • 我会尝试解决这个问题并将其放入github.com/robertpi/FsLinqFixed,如果您将初始修复的补丁发送给我,我们将不胜感激。
    • @Robert 我分叉了您的存储库并发送了包含更改的拉取请求。干杯。
    • 终于可以合并更改并将它们推送到 nuget:nuget.org/List/Packages/FsLinqFixed
    【解决方案2】:

    您可以尝试引用如下:

    <@fun u -> u.FirstName.Equals("Bob")@>
    

    【讨论】:

    • 此报价将适用于上述新版本的电源组和 LinqToSql。但是引用&lt;@ fun u -&gt; u.Username &lt;&gt; "sam0" @&gt; 将不起作用。然而,它会在以前的版本中。
    • @David Dickson - 是的,你是对的。我的回答只是您现在可以使用最新版本的替代方案。对于&lt;@ fun u -&gt; u.Username &lt;&gt; "sam0" @&gt;,您可以使用&lt;@ fun u -&gt; u.Username.Equals("sam0").Equals(false) @&gt;
    猜你喜欢
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多