9 people like it.

Extra Micro ORM

Easy database access.

Micro ORM

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
namespace XMicroOrm

open System
open System.Data
open Microsoft.FSharp.Reflection

[<AutoOpen>]
module Extensions =
    type System.Data.Common.DbProviderFactory with
        member f.CreateConnection(connectionString) =
            let cnn = f.CreateConnection()
            cnn.ConnectionString <- connectionString
            cnn

    type System.Data.IDbConnection with
        member f.CreateCommand(connection, commandText) =
            let cmd = f.CreateCommand()
            cmd.Connection  <- connection
            cmd.CommandText <- commandText
            cmd

[<AutoOpen>]
module (* internal *) Helper =
    let toOptionDynamic (typ: Type) (value: obj) =
        let opttyp = typedefof<Option<_>>.MakeGenericType([|typ|])
        let tag, varr = if DBNull.Value.Equals(value) then 0, [||] else 1, [|value|]
        let case = FSharpType.GetUnionCases(opttyp) |> Seq.find (fun uc -> uc.Tag = tag)
        FSharpValue.MakeUnion(case, varr)

    let optionTypeArg (typ : Type) =
        let isOp = typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<Option<_>>
        if isOp then Some (typ.GetGenericArguments().[0]) else None

type DbEntityField = { Index: int; Name: string; Type: Type }

module DbEntity =
    let name<'R when 'R : not struct> =
        let rty = typeof<'R>
        assert (FSharpType.IsRecord(rty))
        rty.Name

    let fields<'R when 'R : not struct> =
        let rty = typeof<'R>
        assert (FSharpType.IsRecord(rty))
        FSharpType.GetRecordFields(rty)
        |> Seq.mapi (fun i p -> {Index=i; Name=p.Name; Type=p.PropertyType})

    let read<'R when 'R : not struct> (cnn: IDbConnection) sql =
        let rty = typeof<'R>
        assert (FSharpType.IsRecord(rty))
        let makeEntity =
            let mk = FSharpValue.PreComputeRecordConstructor(rty)
            (fun vals -> mk vals :?> 'R)
        let fields = dict <| seq { for fld in fields<'R> -> fld.Name, fld }
        seq { use cmd = cnn.CreateCommand(cnn, sql)
              use reader = cmd.ExecuteReader()
              while reader.Read() do
              yield seq { 0..reader.FieldCount-1 }
                    |> Seq.map (fun i -> reader.GetName(i), reader.GetValue(i))
                    |> Seq.sortBy (fun (n, _) -> fields.[n].Index)
                    |> Seq.map    (fun (n, v) -> match optionTypeArg fields.[n].Type with
                                                 | Some t -> toOptionDynamic t v
                                                 | None   -> v)
                    |> Seq.toArray
                    |> makeEntity }

Usage

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
namespace Sample

open System
open System.Data.Common
open XMicroOrm

type Customer =
    { CustomerID    : int;
      PersonID      : int option;
      StoreID       : int option;
      TerritoryID   : int option;
      AccountNumber : string;
      rowguid       : Guid;
      ModifiedDate  : DateTime }

module Program =
    let provider = @"System.Data.SqlClient"
    let cnnstr = @"Data Source=(LocalDB)\v11.0;Integrated Security=True;"
               + @"AttachDbFilename=D:\AdventureWorks2012_Data.mdf"

    let main _ =
        let factory = DbProviderFactories.GetFactory(provider)
        use cnn = factory.CreateConnection(cnnstr)
        cnn.Open()

        @"SELECT * FROM Sales.Customer"
        |> DbEntity.read<Customer> cnn
        |> Seq.take 10
        |> Seq.iter (printfn "%A")
namespace XMicroOrm
namespace System
namespace System.Data
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
Multiple items
type AutoOpenAttribute =
  inherit Attribute
  new : unit -> AutoOpenAttribute
  new : path:string -> AutoOpenAttribute
  member Path : string

Full name: Microsoft.FSharp.Core.AutoOpenAttribute

--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
namespace System.Data.Common
type DbProviderFactory =
  member CanCreateDataSourceEnumerator : bool
  member CreateCommand : unit -> DbCommand
  member CreateCommandBuilder : unit -> DbCommandBuilder
  member CreateConnection : unit -> DbConnection
  member CreateConnectionStringBuilder : unit -> DbConnectionStringBuilder
  member CreateDataAdapter : unit -> DbDataAdapter
  member CreateDataSourceEnumerator : unit -> DbDataSourceEnumerator
  member CreateParameter : unit -> DbParameter
  member CreatePermission : state:PermissionState -> CodeAccessPermission

Full name: System.Data.Common.DbProviderFactory
val f : Common.DbProviderFactory
member Common.DbProviderFactory.CreateConnection : connectionString:string -> Common.DbConnection

Full name: XMicroOrm.Extensions.CreateConnection
val connectionString : string
val cnn : Common.DbConnection
Common.DbProviderFactory.CreateConnection() : Common.DbConnection
member Common.DbProviderFactory.CreateConnection : connectionString:string -> Common.DbConnection
property Common.DbConnection.ConnectionString: string
type IDbConnection =
  member BeginTransaction : unit -> IDbTransaction + 1 overload
  member ChangeDatabase : databaseName:string -> unit
  member Close : unit -> unit
  member ConnectionString : string with get, set
  member ConnectionTimeout : int
  member CreateCommand : unit -> IDbCommand
  member Database : string
  member Open : unit -> unit
  member State : ConnectionState

Full name: System.Data.IDbConnection
val f : IDbConnection
member IDbConnection.CreateCommand : connection:IDbConnection * commandText:string -> IDbCommand

Full name: XMicroOrm.Extensions.CreateCommand
val connection : IDbConnection
val commandText : string
val cmd : IDbCommand
IDbConnection.CreateCommand() : IDbCommand
member IDbConnection.CreateCommand : connection:IDbConnection * commandText:string -> IDbCommand
property IDbCommand.Connection: IDbConnection
property IDbCommand.CommandText: string
val toOptionDynamic : typ:Type -> value:obj -> obj

Full name: XMicroOrm.Helper.toOptionDynamic
val typ : Type
type Type =
  inherit MemberInfo
  member Assembly : Assembly
  member AssemblyQualifiedName : string
  member Attributes : TypeAttributes
  member BaseType : Type
  member ContainsGenericParameters : bool
  member DeclaringMethod : MethodBase
  member DeclaringType : Type
  member Equals : o:obj -> bool + 1 overload
  member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
  member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
  ...

Full name: System.Type
val value : obj
type obj = Object

Full name: Microsoft.FSharp.Core.obj
val opttyp : Type
val typedefof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typedefof
module Option

from Microsoft.FSharp.Core
val tag : int
val varr : obj []
type DBNull =
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member GetTypeCode : unit -> TypeCode
  member ToString : unit -> string + 1 overload
  static val Value : DBNull

Full name: System.DBNull
field DBNull.Value
Object.Equals(obj: obj) : bool
val case : UnionCaseInfo
type FSharpType =
  static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetFunctionElements : functionType:Type -> Type * Type
  static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetTupleElements : tupleType:Type -> Type []
  static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
  static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
  static member IsFunction : typ:Type -> bool
  static member IsModule : typ:Type -> bool
  static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
  static member IsTuple : typ:Type -> bool
  ...

Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.GetUnionCases : unionType:Type * ?allowAccessToPrivateRepresentation:bool -> UnionCaseInfo []
static member FSharpType.GetUnionCases : unionType:Type * ?bindingFlags:Reflection.BindingFlags -> UnionCaseInfo []
module Seq

from Microsoft.FSharp.Collections
val find : predicate:('T -> bool) -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.find
val uc : UnionCaseInfo
property UnionCaseInfo.Tag: int
type FSharpValue =
  static member GetExceptionFields : exn:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetRecordField : record:obj * info:PropertyInfo -> obj
  static member GetRecordFields : record:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetTupleField : tuple:obj * index:int -> obj
  static member GetTupleFields : tuple:obj -> obj []
  static member GetUnionFields : value:obj * unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo * obj []
  static member MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
  static member MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:BindingFlags -> obj
  static member MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
  static member MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:BindingFlags -> obj
  ...

Full name: Microsoft.FSharp.Reflection.FSharpValue
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?allowAccessToPrivateRepresentation:bool -> obj
static member FSharpValue.MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:Reflection.BindingFlags -> obj
val optionTypeArg : typ:Type -> Type option

Full name: XMicroOrm.Helper.optionTypeArg
val isOp : bool
property Type.IsGenericType: bool
Type.GetGenericTypeDefinition() : Type
union case Option.Some: Value: 'T -> Option<'T>
Type.GetGenericArguments() : Type []
union case Option.None: Option<'T>
type DbEntityField =
  {Index: int;
   Name: string;
   Type: Type;}

Full name: XMicroOrm.DbEntityField
DbEntityField.Index: int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
DbEntityField.Name: string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Multiple items
DbEntityField.Type: Type

--------------------
type Type =
  inherit MemberInfo
  member Assembly : Assembly
  member AssemblyQualifiedName : string
  member Attributes : TypeAttributes
  member BaseType : Type
  member ContainsGenericParameters : bool
  member DeclaringMethod : MethodBase
  member DeclaringType : Type
  member Equals : o:obj -> bool + 1 overload
  member FindInterfaces : filter:TypeFilter * filterCriteria:obj -> Type[]
  member FindMembers : memberType:MemberTypes * bindingAttr:BindingFlags * filter:MemberFilter * filterCriteria:obj -> MemberInfo[]
  ...

Full name: System.Type
module DbEntity

from XMicroOrm
val name<'R (requires reference type)> : string

Full name: XMicroOrm.DbEntity.name
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val rty : Type
val typeof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typeof
static member FSharpType.IsRecord : typ:Type * ?allowAccessToPrivateRepresentation:bool -> bool
static member FSharpType.IsRecord : typ:Type * ?bindingFlags:Reflection.BindingFlags -> bool
property Reflection.MemberInfo.Name: string
val fields<'R (requires reference type)> : seq<DbEntityField>

Full name: XMicroOrm.DbEntity.fields
static member FSharpType.GetRecordFields : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> Reflection.PropertyInfo []
static member FSharpType.GetRecordFields : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> Reflection.PropertyInfo []
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
val p : Reflection.PropertyInfo
property Reflection.PropertyInfo.PropertyType: Type
val read : cnn:IDbConnection -> sql:string -> seq<'R> (requires reference type)

Full name: XMicroOrm.DbEntity.read
val cnn : IDbConnection
val sql : string
val makeEntity : (obj [] -> 'R) (requires reference type)
val mk : (obj [] -> obj)
static member FSharpValue.PreComputeRecordConstructor : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> (obj [] -> obj)
static member FSharpValue.PreComputeRecordConstructor : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> (obj [] -> obj)
val vals : obj []
val fields : Collections.Generic.IDictionary<string,DbEntityField>
val dict : keyValuePairs:seq<'Key * 'Value> -> Collections.Generic.IDictionary<'Key,'Value> (requires equality)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.dict
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val fld : DbEntityField
val reader : IDataReader
IDbCommand.ExecuteReader() : IDataReader
IDbCommand.ExecuteReader(behavior: CommandBehavior) : IDataReader
IDataReader.Read() : bool
property IDataRecord.FieldCount: int
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
IDataRecord.GetName(i: int) : string
IDataRecord.GetValue(i: int) : obj
val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.sortBy
val n : string
val v : obj
val t : Type
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
type Customer =
  {CustomerID: int;
   PersonID: int option;
   StoreID: int option;
   TerritoryID: int option;
   AccountNumber: string;
   rowguid: Guid;
   ModifiedDate: DateTime;}

Full name: Sample.Customer
Customer.CustomerID: int
Customer.PersonID: int option
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
Customer.StoreID: int option
Customer.TerritoryID: int option
Customer.AccountNumber: string
Customer.rowguid: Guid
Multiple items
type Guid =
  struct
    new : b:byte[] -> Guid + 4 overloads
    member CompareTo : value:obj -> int + 1 overload
    member Equals : o:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member ToByteArray : unit -> byte[]
    member ToString : unit -> string + 2 overloads
    static val Empty : Guid
    static member NewGuid : unit -> Guid
    static member Parse : input:string -> Guid
    static member ParseExact : input:string * format:string -> Guid
    ...
  end

Full name: System.Guid

--------------------
Guid()
Guid(b: byte []) : unit
Guid(g: string) : unit
Guid(a: int, b: int16, c: int16, d: byte []) : unit
Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
Customer.ModifiedDate: DateTime
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
module Program

from Sample
val provider : string

Full name: Sample.Program.provider
val cnnstr : string

Full name: Sample.Program.cnnstr
val main : 'a -> unit

Full name: Sample.Program.main
val factory : DbProviderFactory
type DbProviderFactories =
  static member GetFactory : providerInvariantName:string -> DbProviderFactory + 1 overload
  static member GetFactoryClasses : unit -> DataTable

Full name: System.Data.Common.DbProviderFactories
DbProviderFactories.GetFactory(providerRow: Data.DataRow) : DbProviderFactory
DbProviderFactories.GetFactory(providerInvariantName: string) : DbProviderFactory
val cnn : DbConnection
DbProviderFactory.CreateConnection() : DbConnection
member DbProviderFactory.CreateConnection : connectionString:string -> DbConnection
DbConnection.Open() : unit
val read : cnn:Data.IDbConnection -> sql:string -> seq<'R> (requires reference type)

Full name: XMicroOrm.DbEntity.read
val take : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.take
val iter : action:('T -> unit) -> source:seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iter
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn

More information

Link:http://fssnip.net/gE
Posted:11 years ago
Author:igeta
Tags: database , orm