Linq 基于属性参数化F#查询
我想找出几个表上的一些常见查询。在一个非常简单的示例中,所有表都有一个Linq 基于属性参数化F#查询,linq,f#,type-providers,quotations,Linq,F#,Type Providers,Quotations,我想找出几个表上的一些常见查询。在一个非常简单的示例中,所有表都有一个DataDate列,因此我有如下查询: let dtexp1 = query { for x in table1 do maxBy x.Datadate } let dtexp2 = query { for x in table2 do maxBy x.Datadate } 基于a,我可以执行以下操作: let mkQuery t q = query { for rows in t do maxBy ((
DataDate
列,因此我有如下查询:
let dtexp1 = query { for x in table1 do maxBy x.Datadate }
let dtexp2 = query { for x in table2 do maxBy x.Datadate }
基于a,我可以执行以下操作:
let mkQuery t q =
query { for rows in t do maxBy ((%q) rows) }
let getMaxDt1 = mkQuery table1 (<@ fun q -> q.Datadate @>)
let getMaxDt2 = mkQuery table2 (<@ fun q -> q.Datadate @>)
除非我能抽象出由生成的表1、表2等的类型。答案在很大程度上取决于您需要构造什么样的查询以及它们是静态的还是动态的。一般来说:
- 如果LINQ主要是静态的,并且您可以轻松列出所有查询所需的所有模板,那么LINQ是非常棒的—主要的优点是它静态地检查查询类型
- 当您的查询结构非常动态时,LINQ就不太好了,因为这样您就需要编写大量的引用,并且类型检查有时会妨碍您
type Column = string
type Table = string
type QueryAggregate =
| MaxBy of Column
type Query =
{ Table : Table
Aggregate : QueryAggregate }
然后,您可以使用以下方法创建两个查询:
let q1 = { Table = "table1"; Aggregate = MaxBy "Datadate" }
let q2 = { Table = "table2"; Aggregate = MaxBy "Datadate" }
将这些查询转换为SQL非常简单:
let translateAgg = function
| MaxBy col -> sprintf "MAX(%s)" col
let translateQuery q =
sprintf "SELECT %s FROM %s" (translateAgg q.Aggregate) q.Table
根据查询的丰富程度,转换可能会变得非常复杂,但是如果结构相当简单,那么这可能比使用LINQ构造查询更容易。正如我所说,如果不知道确切的用例,很难说什么会更好 thx。这是一个有趣的方法。我会仔细考虑的。是的,查询是动态的,我可以用报价来处理。但我很好奇,是否有什么方法可以让它更习惯/更简单,使用泛型或接口,或者(gasp)SRTP作为最后的手段。如果你走上“字符串-concat”的道路:确保你的应用程序不会进入SQL注入的危险区域。@CaringDev很好。使用
SqlCommand
运行结果查询时,最好的选择是通过SqlParameter
添加参数(请参阅)。这样,用户输入将永远不会与查询字符串连接,您应该不会有问题!
let translateAgg = function
| MaxBy col -> sprintf "MAX(%s)" col
let translateQuery q =
sprintf "SELECT %s FROM %s" (translateAgg q.Aggregate) q.Table