我有以下代码从SQL导入到F#并将信息转换为矩阵。
我这里有一个用户有4个标准的例子,但如果我想再添加2个标准(并且标准的数量可能会改变),我将不得不手动完成(在此代码中维度不会自动完成)并且必须写入列的名称)。
此解决方案有效,但我必须手动检查SQL表中的演进,并手动更改代码中列的名称,这很快就会非常痛苦。所以我的问题是:
您是否看到了自动考虑SQL表的维度的方法,更一般地说,您是否有办法进行此导入而无需手动编写每列的名称(“Criteria0_ID”等等) SQL中“列”的名称?)?提前告诉我们!
type user = {
Criteria0_ID : int;
Criteria1_ID : int;
Criteria2_ID : int;
Criteria3_ID : int}
// Extraction from SQL
module ReadSQl =
let GetUsers = seq {
let connStr = new SqlConnectionStringBuilder(DataSource="localhost\sqlexpress", IntegratedSecurity=true, InitialCatalog="TestExtractionF#")
use cnn = new SqlConnection(connStr.ConnectionString)
use cmd = new SqlCommand("SELECT * FROM SyntheseTest", cnn)
cnn.Open()
use reader = cmd.ExecuteReader()
while reader.Read() do
yield {
Criteria0_ID = unbox(reader.["Criteria0_ID"])
Criteria1_ID = unbox(reader.["Criteria1_ID"])
Criteria2_ID = unbox(reader.["Criteria2_ID"])
Criteria3_ID = unbox(reader.["Criteria3_ID"])
}
}
// Sequence transformation
let UserBase = GetUsers |> Seq.toList
// Creating the matrix
let matrixUA =
Matrix.ofList
[ // Create list containing rows from the database
for row in UserBase do
// For each row, return list of columns (float values)
yield [ float row.Criteria0_ID;
float row.Criteria1_ID;
float row.Criteria2_ID;
float row.Criteria3_ID;
] ]
matrixUA
答案 0 :(得分:3)
使用FsSql你可以这样写:
let readMatrixUA() =
let connStr = SqlConnectionStringBuilder(DataSource="localhost\sqlexpress", IntegratedSecurity=true, InitialCatalog="TestExtractionF#")
use cnn = new SqlConnection(connStr.ConnectionString)
cnn.Open()
Sql.execReader (Sql.withConnection cnn) "select * from SyntheseTest" []
|> Sql.map Sql.asNameValue
|> Seq.map (Seq.map (snd >> Option.fromDBNull >> Option.getOrDefault >> float))
|> Matrix.ofSeq
答案 1 :(得分:1)
在当前版本的F#中,您始终需要自己定义user
类型。你可以做一些技巧,使复制更好。最简单的方法是使用?
运算符来获取以下语法:
let (?) (reader:SqlDataReader) (name:string) : 'T =
unbox (reader.[name])
yield { Criteria1_ID = reader?Criteria1_ID
Criteria2_ID = reader?Criteria2_ID
Criteria3_ID = reader?Criteria3_ID }
您可以更进一步 - 如果您打开Microsoft.FSharp.Reflection
,您可以使用FSharpType.GetRecordFields
获取字段的名称(使用反射)并动态进行复制 - 如果您使用此方法,你只需要改变记录声明。对于当前版本的F#,这可能就此而言。
但是,F#3.0(来自Visual Studio 11)包含一个名为 type provders 的功能,它实质上允许您自动导入架构。您可以通过Don Syme(见for example this)和MSDN (draft) documentation的会谈了解更多信息。