Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 以编程方式构造计算表达式_F# - Fatal编程技术网

F# 以编程方式构造计算表达式

F# 以编程方式构造计算表达式,f#,F#,我想创建一个方法,该方法将使用FSharp.Data.TypeProviders和提供的数据结构中的LINQ2SQL或LINQ2Entities构造一个等价的查询{…}计算表达式,即: 收款客户,[ 字段customerId; 集合顺序,[ 字段orderId]] 为此,我首先需要了解如何将查询转换为代码。以以下查询为例: 质疑{ 对于数据库中的c,客户会这样做 选择c.CustomerID,查询{ 对于c中的o,订单是多少 选择o.OrderID }|>顺序列表 } 如果没有计算表达式语法,

我想创建一个方法,该方法将使用FSharp.Data.TypeProviders和提供的数据结构中的LINQ2SQL或LINQ2Entities构造一个等价的查询{…}计算表达式,即:

收款客户,[ 字段customerId; 集合顺序,[ 字段orderId]] 为此,我首先需要了解如何将查询转换为代码。以以下查询为例:

质疑{ 对于数据库中的c,客户会这样做 选择c.CustomerID,查询{ 对于c中的o,订单是多少 选择o.OrderID }|>顺序列表 }
如果没有计算表达式语法,它会是什么样子?

我不建议以编程方式生成F查询

查询的主要目的是使编写外观良好的F源代码成为可能。当它们被执行时,您编写的代码首先被转换为LINQ风格的表达式树,然后被转换为SQL查询。如果您成功地将查询规范转换为F query,您将得到如下结果:

 +------------+    +----------+    +----------------------+    +-----+
 | Your query | -> | F# query | -> | LINQ expression tree | -> | SQL |
 +------------+    +----------+    +----------------------+    +-----+
多重转换没有错,但有许多因素使得通过F query的路径更加复杂:

在您的查询格式中,事物似乎表示为字符串。所以,您需要从字符串转到.NET MethodInfo才能回到字符串

使用F querys/LINQ,您可以返回类型化对象,这是主要的好处之一,但是如果动态构建查询,您将只返回一组obj值,并且必须使用反射或类似的方法来访问它们


TL;DR-我认为直接获取查询表示并生成SQL要容易得多。转换的结构类似于生成F查询,但您不必乱用引号和反射。

如果您想了解某些东西是如何分解的,只需将其放入引号中即可。如果你用你的例子,你会看到

<@ 
    query {
        for c in db.Customers do
        select (c.CustomerID, query {
            for o in c.Orders do
            select o.OrderID
        } |> Seq.toList)
    } 
@>
大致相当于

query.Run 
    <@ query.Select(query.For(query.Source db.Customers, 
                              fun c -> query.Yield c), 
                    fun c -> 
                        c.CustomerID, 
                        query.Run <@ 
                                    query.Select(query.For(query.Source c.Orders, 
                                                           fun o -> query.Yield o), 
                                                 fun o -> o.OrderID) @> 
                             |> Seq.toList) @>

我已经清理了一些无关的变量。我同意Tomas的观点,与直接创建这样一个表达式相比,可能有更好的方法来实现您的目标。

这是一个非常好的计算表达式入门。每个关键字对应的内容在MSDN中都有很好的文档记录-例如。。。in转换为对生成器类型的For函数的调用。为了得到准确的代码,你可以使用反编译器。谢谢Luaan。不幸的是,我在尝试使用查询表达式进行简单的转换时失败了。我也尝试过阅读反编译的代码。然而,这个查询的主体是直接写入数组并使用单个方法调用的typeof和字节数的混合体——可能该查询主体的一部分实际上是一个F引号。对于人类来说也不是特别可读的。有许多类型提供程序。F已经提供了类型提供程序,并且从版本3开始。但是..使用SqlCommandProvider,尽管您根本不需要映射。提供程序将表公开为类型。可以将其视为类型安全、启用LINQ的Dapper@PanagiotisKanavos-如果您仔细阅读我的问题,您的所有问题都已得到回答:1。在示例中,我提到了我正在将FSharp.Data.TypeProviders与LinqToSql一起使用的特定NuGet包。2.此外,我还需要返回具有嵌套的一对多关系的实体,该关系也在示例中给出。所以,衣冠楚楚的供应商不会帮我的。此外,在这里擦除类型提供程序可能会失败。3.我清楚地提到,我需要解构一个查询所有类型的提供者,公开SQL数据库上的查询表达式。我也在考虑直接转换为SQL,但有一个陷阱——我必须处理一对多和多对多关系,并检测正确的外键。从LINQ的角度来看,列和连接都只是属性。另一种选择是从预定义的F代码块组合查询,然后将这些代码块放在一起,请参见。如果你的词汇量相当有限,那么这可能会更好。我的想法是基于这样一个事实:你的样本中有字符串——听起来非常通用。太好了!但是你在哪里/如何看到引用产生了什么?@DaxFohl-我刚刚使用了F Interactive。您需要确保所有标识符事先都已正确定义,并且输出不是超级可读的,例如,您将看到PropertyGet Some o,OrderID,[]等内容,而不是o.OrderID,但除此之外,它是完全直观的。