我一直在使用FSharpDAL读取 Mysql 数据库中的数据表。它运行良好,但您必须为其提供记录类型。这意味着您必须为每个表定义一个记录类型。我想从表模式中自动生成记录类型。此外,当表列可以为空时,我希望相应的记录字段成为选项类型。
有什么东西可以做到这一点吗?(直到类型提供者到达)
非常感谢
注意我试图做我的版本(它用记录类型编译一个模块),似乎工作但它很难看:(感谢@DannyAsher的编译代码)
let typeString conString (table:string) =
use con = new MySqlConnection(conString)
con.Open()
use cmd = new MySqlCommand(("select * from "+table),con)
let schema = cmd.ExecuteReader().GetSchemaTable()
let schemaData =
[for col in schema.Columns do
yield! [for row in schema.Rows ->
//System.Console.WriteLine(col.ColumnName+" "+string row.[col])
(col.ColumnName),(string row.[col])]]
|>Seq.filter(fun (name,_) ->
((name="ColumnName")||(name="DataType"))||(name="AllowDBNull"))
|>Seq.groupBy(fst)
|>Seq.cache
let columnsNames = snd(schemaData|>Seq.nth(0))
let colDataTypes = snd(schemaData|>Seq.nth(1))
let optionType = snd(schemaData|>Seq.nth(2))
let toCompileType =
(Seq.zip3 columnsNames colDataTypes optionType
|> Seq.map(fun ((_,colName),(_,colType),(_,allowNull)) ->
if allowNull="True" then
colName+":"+colType+" option;"
else
colName+":"+colType+";"
)
|>Seq.fold(fun res elem ->res+elem) ("type "+table+"={"))+"}"
toCompileType
#r "FSharp.Compiler.dll"
#r "FSharp.Compiler.CodeDom.dll"
open System
open System.IO
open System.CodeDom.Compiler
open Microsoft.FSharp.Compiler.CodeDom
let CompileFSharpString(str, assemblies, output) =
use pro = new FSharpCodeProvider()
let opt = CompilerParameters(assemblies, output)
let res = pro.CompileAssemblyFromSource( opt, [|str|] )
if res.Errors.Count = 0 then
Some(FileInfo(res.PathToAssembly))
else
None
let (++) v1 v2 = Path.Combine(v1, v2)
let defaultAsms = [||]
let randomFile() = __SOURCE_DIRECTORY__ ++ Path.GetRandomFileName() + ".dll"
type System.CodeDom.Compiler.CodeCompiler with
static member CompileFSharpString (str, ?assemblies, ?output) =
let assemblies = defaultArg assemblies defaultAsms
let output = defaultArg output (randomFile())
CompileFSharpString(str, assemblies, output)
let tables = [|"users";"toys"|]
let compileTypes conString tables =
let m= "namespace Toto
module Types =
"
let str = tables|>Seq.fold(fun res elem ->
res+"\n "+(typeString conString elem)) m
// Create the assembly
CodeCompiler.CompileFSharpString(str)
let conString = "connectionstring"
let file =compileTypes conString tables
#r "theFileName"
open Toto.Types