首页 > 解决方案 > 在 F# 中使用用于 SQL Server 的 SqlDataProvider 更新数据库行

问题描述

我是 F# 的新手,我正在尝试使用SqlDataProvider.

我想要完成的事情是更新我使用 Individuals 属性预取的 Db 行。然后我正在更改字段并提交更新,但似乎SqlDataProvider没有跟踪更改。

这是代码:

let context = SqlFunctions.Sql.GetDataContext()         
    let engeneering = context.HumanResources.Department.Individuals.``1``   
    engeneering.Name <- "Eng."
    context.SubmitUpdates()

SqlFunction.Sql实现如下:

module SqlFunctions
open FSharp.Data.Sql
type Sql = SqlDataProvider<Common.DatabaseProviderTypes.MSSQLSERVER, 
                            "Server=************;Database=AdventureWorks2014;Trusted_Connection=True;">

标签: f#f#-data

解决方案


欢迎来到社区!

虽然 SqlDataProvider 是一个出色的工具,但如果您愿意使用它,我建议您使用一些更简单的构造。我想很多时候,当新人加入时,他们会被所有花哨的玩具所吸引,以至于很容易忽略它仍然只是普通的旧 .NET的事实。

话虽如此,我说我们从小处着手,大到结束。我们将通过直接查看您的问题范围来实现这一点,并且在 F# 的真正本质中,我们自己编写了如此漂亮的小函数,以使最终结果简洁明了。

我们的最终目标是支持这样的语法:

// Define a reusable "update department" function
let updateDepartment departmentId name connStr = 
    use conn = newConnection connStr
    exec 
        "UPDATE HumanResources.Department SET Name = @name WHERE DepartmentId = @departmentId"  
        [("departmentId", departmentId);("name", name)] 
        conn      

let connStr = "..."
updateDepartment 1 "eng" connStr |> ignore

为此,您实际上只需要很少的代码,这是 F# 的主要优点之一。我们知道我们需要:

  • 一种创建连接的方式(即连接工厂)
  • 一种执行语句的方法(即INSERT, UPDATE
  • 一种查询记录的方法(即SELECT
module SQL =
    open System.Data
    open System.Data.SqlClient

    let newConnection connectionString =
        let conn = new SqlConnection(connectionString)
        conn.Open()
        conn

    let createParameter (cmd: SqlCommand) (name, value) =
        let p = cmd.CreateParameter()
        p.ParameterName <- name
        p.Value <- value
        p

    let addParameter (cmd: SqlCommand) (p : SqlParameter) = 
        cmd.Parameters.Add(p) |> ignore

    let newCommand sql parameters conn =        
        let cmd = new SqlCommand(connection = conn, cmdText = sql)
        cmd.CommandType <- CommandType.Text        

        let createParam = createParameter cmd
        let addParam = addParameter cmd
        parameters 
        |> Seq.iter (fun p -> p |> createParam |> addParam)
        cmd 

    let exec sql param conn =
        let cmd = newCommand sql param conn
        cmd.ExecuteNonQuery()

    let query sql param map conn =
        let cmd = newCommand sql param conn
        use rd = cmd.ExecuteReader()
        [ while rd.Read() do
            yield map rd ]

因此,在大约 30 行代码中,我们为自己创建了一个小型、易于理解且(在我看来)自我记录的解决方案。


推荐阅读