|
@@ -2,8 +2,7 @@ namespace App
|
|
|
|
|
|
open System
|
|
|
open System.Data
|
|
|
-open System.Data.Common
|
|
|
-open System.Text
|
|
|
+open Microsoft.Extensions.ObjectPool
|
|
|
open Npgsql
|
|
|
|
|
|
|
|
@@ -15,6 +14,7 @@ module Db =
|
|
|
use db = new NpgsqlConnection(ConnectionString)
|
|
|
use cmd = db.CreateCommand(CommandText = "SELECT id, message FROM fortune")
|
|
|
do! db.OpenAsync()
|
|
|
+ do! cmd.PrepareAsync()
|
|
|
use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection)
|
|
|
while! rdr.ReadAsync() do
|
|
|
result.Add { id = rdr.GetInt32(0); message = rdr.GetString(1) }
|
|
@@ -31,7 +31,7 @@ module Db =
|
|
|
TypedValue = Random.Shared.Next(1, 10001)
|
|
|
)
|
|
|
cmd.Parameters.Add(id) |> ignore
|
|
|
- cmd
|
|
|
+ struct(cmd, id)
|
|
|
|
|
|
let private readSingleRow (cmd: NpgsqlCommand) =
|
|
|
task {
|
|
@@ -43,41 +43,46 @@ module Db =
|
|
|
let loadSingleRow () =
|
|
|
task {
|
|
|
use db = new NpgsqlConnection(ConnectionString)
|
|
|
+ let struct(cmd', _) = createReadCommand db
|
|
|
+ use cmd = cmd'
|
|
|
do! db.OpenAsync()
|
|
|
- use cmd = createReadCommand db
|
|
|
+ do! cmd.PrepareAsync()
|
|
|
return! readSingleRow cmd
|
|
|
}
|
|
|
|
|
|
let private readMultipleRows (count: int) (conn: NpgsqlConnection) =
|
|
|
let result = Array.zeroCreate count
|
|
|
task {
|
|
|
- use cmd = createReadCommand conn
|
|
|
+ let struct(cmd', idParam) = createReadCommand conn
|
|
|
+ use cmd = cmd'
|
|
|
for i in 0..result.Length-1 do
|
|
|
- cmd.Parameters["@Id"].Value <- Random.Shared.Next(1, 10001)
|
|
|
let! row = readSingleRow cmd
|
|
|
result[i] <- row
|
|
|
+ idParam.TypedValue <- Random.Shared.Next(1, 10001)
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
let loadMultipleRows (count: int) =
|
|
|
task {
|
|
|
- use db = new NpgsqlConnection(ConnectionString)
|
|
|
+ use db = new NpgsqlConnection(MultiplexedConnectionString)
|
|
|
do! db.OpenAsync()
|
|
|
return! readMultipleRows count db
|
|
|
}
|
|
|
|
|
|
let private maxBatch = 500
|
|
|
let private queries = Array.zeroCreate (maxBatch + 1)
|
|
|
+ let private stringBuilderPool = DefaultObjectPoolProvider().CreateStringBuilderPool()
|
|
|
let private batchUpdateString batchSize =
|
|
|
match queries[batchSize] with
|
|
|
| null ->
|
|
|
let lastIndex = batchSize - 1
|
|
|
- let sb = StringBuilder()
|
|
|
+ let sb = stringBuilderPool.Get()
|
|
|
sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ") |> ignore
|
|
|
for i in 0..lastIndex-1 do
|
|
|
sb.AppendFormat("(@Id_{0}, @Rn_{0}), ", i) |> ignore
|
|
|
sb.AppendFormat("(@Id_{0}, @Rn_{0}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id", lastIndex) |> ignore
|
|
|
let result = sb.ToString()
|
|
|
+ stringBuilderPool.Return(sb)
|
|
|
queries[batchSize] <- result
|
|
|
result
|
|
|
| q ->
|
|
@@ -95,15 +100,15 @@ module Db =
|
|
|
for i in 0..results.Length-1 do
|
|
|
let randomNumber = Random.Shared.Next(1, 10001)
|
|
|
let struct(rnParamName, idParamName) = paramNames[i]
|
|
|
- let random = NpgsqlParameter<int>(ParameterName = rnParamName, DbType = DbType.Int32, TypedValue = randomNumber)
|
|
|
- command.Parameters.Add(random) |> ignore
|
|
|
- let id = NpgsqlParameter<int>(ParameterName = idParamName, DbType = DbType.Int32, TypedValue = results[i].id)
|
|
|
- command.Parameters.Add(id) |> ignore
|
|
|
+ command.Parameters.Add(NpgsqlParameter<int>(
|
|
|
+ ParameterName = rnParamName, DbType = DbType.Int32, TypedValue = randomNumber)) |> ignore
|
|
|
+ command.Parameters.Add(NpgsqlParameter<int>(
|
|
|
+ ParameterName = idParamName, DbType = DbType.Int32, TypedValue = results[i].id)) |> ignore
|
|
|
results[i] <- { results[i] with randomnumber = randomNumber }
|
|
|
|
|
|
let doMultipleUpdates (count: int) =
|
|
|
task {
|
|
|
- use conn = new NpgsqlConnection(ConnectionString)
|
|
|
+ use conn = new NpgsqlConnection(MultiplexedConnectionString)
|
|
|
do! conn.OpenAsync()
|
|
|
let! results = readMultipleRows count conn
|
|
|
use cmd = conn.CreateCommand(CommandText = batchUpdateString count)
|