在下面的代码中,我想通过F#在SQL表中插入或更新行。
它需要一个代表用户的元组矩阵和一个相关分数(usrID,score),它们是一些F#计算的结果。
现在我想更新一个名为UserScoresTable的SQL表
我写的代码很有用,但速度很慢。
let cnn = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings.Item("Database").ConnectionString)
cnn.Open()
// Definition d'une fonction qui execute une demande sous MySQL
let execNonQuery s =
let comm = new System.Data.SqlClient.SqlCommand(s, cnn, CommandTimeout = 10)
comm.ExecuteNonQuery() |> ignore
// Definition d'une fonction qui utilise les éléments d'une matrice pour updater une table dans MySQL
let updateMySQLTable (m : Matrix<float * float>) =
for j in 0 .. (snd m.Dimensions) - 1 do
for i in 1 .. (fst m.Dimensions) - 1 do
// first check if the user and score and date do not exist
sprintf "IF NOT EXISTS (SELECT * FROM ProductScores WHERE UserID = %f AND ProductID = %f) INSERT INTO ProductScores (UserID, Score, Date) VALUES (%f, %f,CURRENT_TIMESTAMP)" (fst m.[i, j]) (snd m.[i, j])
|> execNonQuery
// otherwise update the row
sprintf "UPDATE ProductScores SET Score = %f, Date = CURRENT_TIMESTAMP WHERE UserID = %f " (snd m.[i, j]) (fst m.[i, j])
|> execNonQuery
我想通过使用存储过程(例如
)来避免代码中的两个execNonQuery请求CREATE PROCEDURE updateScoreByUsers
-- Add the parameters for the stored procedure here
@UserID int,
@Score float
AS
BEGIN
IF NOT EXISTS
(SELECT * FROM ProductScores WHERE UserID = @UserID )
INSERT INTO
ProductScores (UserID, Score, Date) VALUES (@UserID,@Score,CURRENT_TIMESTAMP)
ELSE
UPDATE ProductScores
SET Score = @Score, Date = CURRENT_TIMESTAMP
WHERE UserID = @UserID
END
GO
但我不知道如何在F#中调用SQL存储过程
如何用F#调用它?
你还有其他改进方法吗?
答案 0 :(得分:3)
将SqlCommand.CommandText
设置为存储过程的名称,并将CommandType
设置为StoredProcedure
。例如
use cmd = new SqlCommand("MyStoredProcedure", con)
cmd.CommandType <- CommandType.StoredProcedure
cmd.ExecuteNonQuery()
如果您在2008年,您可能需要查看MERGE
声明。
要显着提高性能,您需要避免为每个项目进行数据库调用。也许使用SqlBulkCopy
一次将所有数据加载到服务器(使用临时表或指定的临时表),然后使用基于集合的操作(UPDATE
/ INSERT
/ {{1 }})与目标表合并。
答案 1 :(得分:3)
正如其他人所指出的那样,只需在单个SQL命令中执行这两个语句就不会提高性能。为了使其真正高效,您需要将数据从Matrix
传输到数据库,然后更新表。要复制数据,您可以使用SqlBulkCopy
(请参阅MSDN for more info),这样可以有效地上传大量数据。您可以使用它在新表中插入数据,然后运行单个SQL命令来更新实际表中的数据。
除此之外 - Daniel的答案是从F#调用存储的proecdure的最直接方式。如果你想让它更好一点,你也可以使用动态运算符,让你写这样的东西:
db?MyStoredProcedure(userId, scores)
...而不是手动创建和执行SqlCommand
。这可以使用this MSDN article中实现的DynamicDatabase
类型来完成。