F# DynamicOracleDataReader

Dynamic reading from an Oracle database

Implementation

let inline tryUnbox<'a> (x:obj) =
    match x with
    | :? 'a as result -> Some(result)
    | _ -> None

type DynamicOracleDataReader(reader:OracleDataReader) =
    member private x.Reader = reader
    member x.Read() = reader.Read()
    static member (?) (dr:DynamicOracleDataReader, name:string) : 'a option = 
        tryUnbox (dr.Reader.[name])
    interface IDisposable with
        member x.Dispose() = reader.Dispose()

type DynamicOracleCommand(cmd:OracleCommand) =
    member private x.Command = cmd
    static member (?<-) (cmd:DynamicOracleCommand, name:string, value) = 
        let p = new OracleParameter(name, box value) 
        cmd.Command.Parameters.Add(p) |> ignore
    member x.ExecuteNonQuery() = cmd.ExecuteNonQuery()
    member x.ExecuteReader() = new DynamicOracleDataReader(cmd.ExecuteReader())
    member x.ExecuteScalar() = cmd.ExecuteScalar()
    member x.Parameters = cmd.Parameters
    interface IDisposable with
        member x.Dispose() = cmd.Dispose()

type DynamicOracleConnection(connStr:string) =
    let conn = new OracleConnection(connStr)
    member private x.Connection = conn
//    static member (?) (conn:DynamicOracleConnection, name) =
//        let command = new OracleCommand(name, conn.Connection)
//        command.CommandType <- CommandType.Text 
//        new DynamicOracleCommand(command)
    member x.GenerateCommand(query:string) = 
        let command = new OracleCommand(query, conn)
        command.BindByName <- true
        new DynamicOracleCommand(command)
    member x.Open() = conn.Open()

    interface IDisposable with
        member x.Dispose() = conn.Dispose()

Usage

type Order = {
    OrderId: int
    Comments: string option}

let connectionString = 
    "User Id = XXXXXX; " + 
    "Password = XXXXXX; " + 
    "Data Source = " + 
        "(Description = " +
        "(Address = " + 
        "(Protocol = TCP) " + 
        "(Host = 127.0.0.1) " + 
        "(Port = 1521)) " + 
        "(Connect_Data = (Service_Name = XXXXXX)))"

let getOrderByIdQuery =
    "select * " +
    "from ORDERS " +
    "where IDORDER = : orderId " +
    "order by IDORDER"

let getOrderById (orderId: int) = seq {
    use conn = new DynamicOracleConnection(connectionString)
    use cmd = conn.GenerateCommand(getOrderByIdQuery)
    
    cmd?orderId <- orderId

    conn.Open()
    use reader = cmd.ExecuteReader ()

    while (reader.Read()) do
        yield {
            OrderId = defaultArg reader?IDORDER 0
            Comments = reader?COMMENTS}}

References

Leave a Reply

Your email address will not be published. Required fields are marked *