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