假设我有以下几点:
SQL
创建名为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
GOF#
[<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
<?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
<connectionStrings>
<add name="Clm" connectionString="Data Source=localhost;Initial Catalog=Clm;Integrated Security=SSPI" />
</connectionStrings>我需要从表ModelData中获取SQL值。它在代码中的某个地方使用。因此,我有以下函数来添加带有一些默认值的新行,然后返回标识值。
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 ()我使用它从数据库中获取modelId的新标识值。
let modelId = getNewModelDataId conn在大约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其中字符串"Some new data..."表示一些相当大的字符串。这种情况每个modelId只发生一次。上面的代码是有效的。但它看起来太丑了,尤其是t1.Rows |> Seq.find ...☹这个角色,我想我错过了一些关于FSharp.Data.SqlClient类型提供商的东西。如有任何建议,我将不胜感激。
发布于 2019-01-04 03:39:00
首先,最明显的错误是:FSharp.Data.SqlClient类型提供者通过其SqlCommandProvider支持任何DML数据修改语句,包括UPDATE。因此,通过将模型拉到客户端、修改并向后推回服务器而不是所有的爵士乐,可以通过以下方式实现
...
use cmd = SqlCommandProvider<
"UPDATE [dbo].[ModelData] SET [modelData]=@ModelData WHERE [modelId]=@ModelId",
conn>(conn)
cmd.Execute(ModelData="Some new data...", ModelId=modelId) |> ignore
...不太明显的问题与identity field的使用有关。听起来,除了唯一地识别每一种新模式之外,它没有任何特殊的角色。因此,与其修补创建假记录,然后从服务器上提取其id,然后用实际值更新具有此id的记录,为什么不只是:
modelUid的附加列统一标识符GUID生成一个新的System.Guid.NewGuid(),开始创建每个新模型INSERT对modelUid字段使用相同的GUID。注意,通过这种方法,您还只使用了SqlCommandProvider类型的FSharp.Data.SqlClient类型提供程序,所以事情仍然很简单。
https://stackoverflow.com/questions/54013601
复制相似问题