[英]F# - FSharp.Data.SqlClient - update row after getting identity value
Let's say that I have the following: 假设我有以下几点:
SQL SQL
Create database called Clm
, then run this script: 创建名为
Clm
数据库,然后运行以下脚本:
CREATE TABLE dbo.ModelData(
modelId bigint IDENTITY(1,1) NOT NULL,
numberOfAminoAcids int NOT NULL,
maxPeptideLength int NOT NULL,
seed int NOT NULL,
fileStructureVersion nvarchar(50) NOT NULL,
modelData nvarchar(max) NOT NULL,
createdOn datetime NOT NULL,
CONSTRAINT PK_ModelData PRIMARY KEY CLUSTERED
(
modelId ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY TEXTIMAGE_ON PRIMARY
GO
ALTER TABLE dbo.ModelData ADD CONSTRAINT DF_ModelData_createdOn DEFAULT (getdate()) FOR createdOn
GO
F# F#
[<Literal>]
let ClmDbName = "Clm"
[<Literal>]
let AppConfigFile = __SOURCE_DIRECTORY__ + "\.\App.config"
[<Literal>]
let ClmConnectionString = "Server=localhost;Database=" + ClmDbName + ";Integrated Security=SSPI"
[<Literal>]
let ClmSqlProviderName = "name=" + ClmDbName
type ClmDB = SqlProgrammabilityProvider<ClmSqlProviderName, ConfigFile = AppConfigFile>
type ModelDataTable = ClmDB.dbo.Tables.ModelData
type ModelDataTableRow = ModelDataTable.Row
type ModelDataTableData =
SqlCommandProvider<"select * from dbo.ModelData where modelId = @modelId", ClmConnectionString, ResultType.DataReader>
App.config App.config中
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<connectionStrings configSource="db.config" />
<runtime>
<gcAllowVeryLargeObjects enabled="true" />
</runtime>
</configuration>
db.config db.config
<connectionStrings>
<add name="Clm" connectionString="Data Source=localhost;Initial Catalog=Clm;Integrated Security=SSPI" />
</connectionStrings>
I need to get SQL identity value from table ModelData
. 我需要从表
ModelData
获取SQL身份值。 It is used somewhere in the code. 它在代码中的某处使用。 So, I have the following function to add a new row with some default values and then get identity value back.
因此,我具有以下功能,以使用一些默认值添加新行,然后返回标识值。
let getNewModelDataId (conn : SqlConnection) =
let t = new ModelDataTable()
let r =
t.NewRow(
numberOfAminoAcids = 0,
maxPeptideLength = 0,
seed = 0,
fileStructureVersion = "",
modelData = "",
createdOn = DateTime.Now
)
t.Rows.Add r
t.Update(conn) |> ignore
r.modelId
let openConnIfClosed (conn : SqlConnection) =
match conn.State with
| ConnectionState.Closed -> do conn.Open()
| _ -> ignore ()
And the I use it to get new identity value of modelId
from the database. 我使用它从数据库中获取
modelId
新标识值。
let modelId = getNewModelDataId conn
The after about 0.5 – 1.5 hours of execution time I need to update some data, eg 在大约0.5 – 1.5小时的执行时间之后,我需要更新一些数据,例如
use d = new ModelDataTableData(conn)
let t1 = new ModelDataTable()
d.Execute(modelId = modelId) |> t1.Load
let r1 = t1.Rows |> Seq.find (fun e -> e.modelId = modelId)
r1.modelData <- "Some new data..."
t1.Update(conn) |> ignore
where the string "Some new data..."
represents some fairly large string. 字符串
"Some new data..."
表示一些相当大的字符串。 This only happens once per modelId
. 每个
modelId
仅发生一次。 The code above does work . 上面的代码可以正常工作 。 But it looks soooo ugly, epsecially the part
t1.Rows |> Seq.find ...
☹ I guess that I am missing something about FSharp.Data.SqlClient
type providers. 但是它看起来非常丑陋,尤其是
t1.Rows |> Seq.find ...
我想我缺少有关FSharp.Data.SqlClient
类型提供程序的信息。 I'd appreciate any advice. 我将不胜感激任何建议。
To begin with the most obvious blunder: FSharp.Data.SqlClient
type provider via its SqlCommandProvider
supports any DML data modification statements, including UPDATE
. 首先介绍最明显的错误:
FSharp.Data.SqlClient
类型提供程序通过其SqlCommandProvider
支持任何DML数据修改语句,包括UPDATE
。 So, instead of all that jazz with pulling the model to the client side, modifying, and pushing back to the server, the same can be achieved by 因此,除了将模型拉到客户端,修改并推回服务器之外,所有这些爵士乐都可以通过以下方式实现:
...
use cmd = SqlCommandProvider<
"UPDATE [dbo].[ModelData] SET [modelData]=@ModelData WHERE [modelId]=@ModelId",
conn>(conn)
cmd.Execute(ModelData="Some new data...", ModelId=modelId) |> ignore
...
The less obvious problem relates to the use of identity field
. 不太明显的问题与
identity field
的使用有关。 It sounds like it does not have any special role beyond uniquely identifying every new model. 听起来,除了唯一地标识每个新模型之外,它没有任何特殊作用。 So, instead of the tinkering with creating a fake record, then pulling its
id
from the server, then updating the record having this id
with real values, why not just: 因此,与其修补虚假记录,而不是从服务器中提取其
id
,然后使用真实值更新具有该id
的记录,不如:
modelUid
of type uniqueidentifier modelUid
类型为uniqueidentifier GUID
with System.Guid.NewGuid()
System.Guid.NewGuid()
生成新的GUID
开始创建每个新模型 INSERT
using the same GUID for modelUid
field INSERT
对它使用相同的GUID作为modelUid
字段即可 Notice, that with such approach you also use just SqlCommandProvider
type of FSharp.Data.SqlClient
type provider, so the things stay simple. 注意,通过这种方法,您还只使用了
FSharp.Data.SqlClient
类型提供程序的SqlCommandProvider
类型,因此事情保持简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.