Класс F # LINQ вписывается в один - PullRequest
0 голосов
/ 29 января 2012

Я учусь LINQ с F # 3.0.Я хочу знать, как преобразовать мой старый класс для использования новых функций LINQ в F # 3.0. Например, я создал простую таблицу данных в 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 я могу создать небольшой класс для извлечения данных из Таблицы 1 и возврата в основную программу.

#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 в класс и использовать его в основной программе?Спасибо, Джон

1 Ответ

3 голосов
/ 29 января 2012

Из вашего вопроса не совсем ясно, чего вы пытаетесь достичь.В ваших примерах ваш новый класс (а также метод) принимают параметр 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) } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...