Paul Nathan
Paul Nathan

Reputation: 40299

F# error: Wrong number of parameters

I am puzzling over some code given to me in a prior SO question I had. Code here

At this line, I get an error saying I have an invalid number of parameters. I don't completely understand what the error is, since all the research I do comes up with this being a correct application of the function.

let result = Seq.to_list(Microsoft.FSharp.Compatibility.Seq.generate_using opener generator)

What's going on here? Why am I getting this kind of error?

Edit: I use the PowerPack.dll reference and the MySQL.Data reference

Code for opener & generator below:

 let opener() = 
        let command = connection.CreateCommand(CommandText = sql, CommandType = System.Data.CommandType.Text)
        command.ExecuteReader()

And generator...

let generator<'a> (reader : System.Data.IDataReader) =
    if reader.Read() then
        let t = typeof<'a>
        let props = t.GetProperties()
        let types = props
                    |> Seq.map (fun x -> x.PropertyType)
                    |> Seq.to_array
        let cstr = t.GetConstructor(types)
        let values = Array.create reader.FieldCount (new obj())
        reader.GetValues(values) |> ignore
        let values = values
                     |> Array.map (fun x -> match x with | :? System.DBNull -> null | _ -> x)
        Some (cstr.Invoke(values) :?> 'a)
    else
        None

Upvotes: 1

Views: 864

Answers (2)

Dan Fitch
Dan Fitch

Reputation: 2529

This post is old and languishing, but are you sure the invalid number of parameters error isn't coming from the Oracle command?

Basically: are you specifying a parameter in the SQL query? The opener function is not applying any parameters.

Upvotes: 1

Robert
Robert

Reputation: 6437

The following type checks for me:

#light
open System.Data
open System.Data.SqlClient
open System.Configuration


type Employee =
    { FirstName: string;
      LastName: string; }

let generator<'a> (reader: IDataReader) =
    if reader.Read() then
        let t = typeof<'a>
        let props = t.GetProperties()
        let types = props
                    |> Seq.map (fun x -> x.PropertyType)
                    |> Seq.to_array
        let cstr = t.GetConstructor(types)
        let values = Array.create reader.FieldCount (new obj())
        reader.GetValues(values) |> ignore
        let values = values
                     |> Array.map (fun x -> match x with | :? System.DBNull -> null | _ -> x)
        Some (cstr.Invoke(values) :?> 'a)
    else
        None

let opener() = 
    let sql = "select * from employees"
    let connection = new SqlConnection(ConfigurationManager.ConnectionStrings.["myConnection"].ConnectionString)
    let command = connection.CreateCommand(CommandText = sql, CommandType = System.Data.CommandType.Text)
    command.ExecuteReader()

let result = Seq.to_list(Microsoft.FSharp.Compatibility.Seq.generate_using opener (generator<Employee>))

It looks like your missing a type annotation to tell the generator what type of list your generating ie: generator<Employee>

Upvotes: 0

Related Questions