2011-01-07 6 views
1

Ich habe FSharpDAL verwendet, um Datentabellen in Mysql-Datenbank zu lesen. Es funktioniert gut, aber Sie müssen es den Datensatztyp bereitstellen. Das bedeutet, dass Sie für jede Tabelle einen Satztyp definieren müssen. Ich möchte den Datensatztyp automatisch aus dem Tabellenschema generieren lassen. Wenn die Tabellenspalte nullfähig ist, möchte ich auch, dass das entsprechende Datensatzfeld ein Optionstyp ist.Automatische Generierung von Datensatztyp basierend auf MySql-Datenbanktabellen zur Verwendung in FSharpDAL

Gibt es da draußen etwas, das das tun kann? (Bis Typ-Provider ankommen)

Vielen Dank

Hinweis habe ich versucht, meine Version zu tun (was ein Modul mit den Aufzeichnungen Typen kompiliert), scheint zu funktionieren, aber seine ugly: (Danke für die @DannyAsher Kompilieren Code)

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 

Antwort

2

Das beste, was ich denken kann, ist die "xsd.exe" tool zu verwenden, die mit VS2010 kommt. Es kann eine Assembly- oder C# -Quelldatei aus einer XML-Beschreibung der Tabelle erstellen.

Die XML-Beschreibung selbst kann aus der Klasse WriteXmlSchema method der Klasse DataSet exportiert werden.

Dies funktioniert nur mit ADO.Net Bindungen, aber MySQL supports those.

+0

danke, ich werde es untersuchen. – jlezard

Verwandte Themen