我正在使用F#3.0学习LINQ。我想知道如何将我的旧类转换为在F#3.0中使用新的LINQ功能 例如,我在SQL Server 2008 R2中创建了一个简单的数据表,数据库名称是myDatabase。
-- Create the Table1 table.
CREATE TABLE [dbo].[Table1] (
[Id] INT NOT NULL,
[TestData1] INT NOT NULL,
[TestData2] FLOAT (53) NOT NULL,
[Name] NTEXT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
USE MyDatabase
INSERT INTO Table1 (Id, TestData1, TestData2, Name)
VALUES(1, 10, 5.5, 'Testing1');
INSERT INTO Table1 (Id, TestData1, TestData2, Name)
VALUES(2, 20, -1.2, 'Testing2');
对于F#2.0,我可以创建一个小类来从Table1中检索数据并返回主程序。
#light
module myData
open System
open System.Collections.Generic
open System.Data
open System.Data.SqlClient
type getData(tableName: string) = class
let sqlConn = "server=(local); Integrated Security=True; Database=MyDatabase"
let connDB = new SqlConnection(sqlConn)
let sqlByFun (cmdText, unwrapping) =
use cmd = new SqlCommand(cmdText, connDB)
let reader = cmd.ExecuteReader()
seq { while reader.Read() do
yield unwrapping(reader) }
let dbTable1(tableName: string) =
let sql = "SELECT Id, TestData1, TestData2, Name FROM Table1 ORDER BY Id"
connDB.Open()
let data = sqlByFun(sqlChanges, (fun reader ->
(reader.GetInt32(0), reader.GetInt32(1),
reader.GetDecimal(2),reader.GetString(3))))
|> Seq.toArray
connDB.Close()
data
member this.getTable(table1) = dbTable1(table1)
然后在我的主程序中:program.fs,我可以使用myData的类:
#light
open myData
open System
open System.Collections.Generic
open System.Data
open System.Data.SqlClient
let db = new myData.getData("Table1")
let table1Data = db.getTable("Table1")
printfn "Done"
现在,使用F#3.0和LINQ,我可以像这样重写这个类:
#light
open System
open System.Data
open System.Data.SqlClient
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
[<Generate>]
type dbSchema = SqlDataConnection<"Data Source=.;Initial Catalog=MyDatabase;Integrated Security=True">
let db = dbSchema.GetDataContext()
let dbTable1(tableName: string) =
let data =
query {
for row in db.Table1 do
sortBy row.Id
select (row.Id, row.TestData1, row.TestData2, row.Name)
}
data
我可以看到这部分,代码更简洁,更清晰,但我希望它在一个类中,可以从我的主程序中调用。 如何将LINQ代码放在类中并由主程序使用? 谢谢, 约翰
答案 0 :(得分:3)
从你的问题来看,你想要实现的目标并不完全清楚。在您的示例中,您的新课程(以及方法)会使用tableName
参数,但无论如何您总是从Table1
读取数据。
编写由表名参数化的LINQ代码并不容易,因为不同的表可能有不同的列,因此您不能使用相同的类型来访问它们。如果您有不同的表具有相同的结构,那么您可以将它们合并到一个表中,并添加一个额外的列来区分记录。如果要访问不同的表,则需要为每个表编写不同的查询。
关于类中的封装,您可以在F#3.0中轻松完成:
// Global declarations for SQL type provider
[<Literal>]
let connStr = "Data Source=.;Initial Catalog=MyDatabase;Integrated Security=True"
[<Generate>]
type dbSchema = SqlDataConnection<connStr>
// Declaration of a class that exposes data access functionality
type DataAccess() =
// Note: You can pass different connection string to 'GetDataContext'
// if you want to keep connection string in config file instead of in code.
let db = dbSchema.GetDataContext()
/// Reads data from Table1
member x.LoadTable1() =
query { for row in db.Table1 do
sortBy row.Id
select (row.Id, row.TestData1, row.TestData2, row.Name) }