Reputation: 40299
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
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
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