2012-01-28 8 views
0

F#3.0でLINQを学習しています。私は古いクラスをF#3.0で新しいLINQ機能を使用するように変換する方法を知りたいです たとえば、SQL Server 2008 R2で単純なデータテーブルを作成しました。データベース名はmyDatabaseです。F#LINQタイプのクラスが1つに収まる

-- 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) 

:F#3.0とLINQは、私はこのようなクラスを再作成することができて、今

#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" 

:program.fsが、私はMYDATAのクラスを使用することができます。私はこの部分を見ることができます

#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コードをクラスに入れてメインプログラムで使用するにはどうすればよいですか? ありがとう、 John

答えて

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) } 
+0

こんにちは、トーマス: ありがとうございました。私は約10のデータテーブルを照会しなければならない、table1は私の例に使用するための唯一の単純なテーブルです。クエリには非常に多くのデータテーブルがあるので、すべてのデータベースクエリを1つのクラスに入れ、メインプログラムから呼び出します。しかし、LINQを使用した後、私はどのように1つのクラスにすべてのデータベースクエリを配置するかわからないので、私は尋ねる。 –

+0

接続文字列をDataAccessクラスのパラメータにしたいのですが? –

関連する問題