Skip to content

Commit 2f5b633

Browse files
committed
Updates to aspnetcore PG database access
1 parent 0e7509d commit 2f5b633

File tree

3 files changed

+73
-38
lines changed

3 files changed

+73
-38
lines changed

frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/BatchUpdateString.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,25 @@ internal sealed class BatchUpdateString
1515
private static readonly string[] _queries = new string[MaxBatch + 1];
1616

1717
public static string Query(int batchSize)
18-
{
19-
if (_queries[batchSize] != null)
20-
{
21-
return _queries[batchSize];
22-
}
23-
24-
var lastIndex = batchSize - 1;
18+
=> _queries[batchSize] is null
19+
? CreateBatch(batchSize)
20+
: _queries[batchSize];
2521

22+
private static string CreateBatch(int batchSize)
23+
{
2624
var sb = StringBuilderCache.Acquire();
2725

2826
if (DatabaseServer == DatabaseServer.PostgreSql)
2927
{
3028
sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
31-
Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@Id_{i}, @Random_{i}), "));
32-
sb.Append($"(@Id_{lastIndex}, @Random_{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
29+
var c = 1;
30+
for (var i = 0; i < batchSize; i++)
31+
{
32+
if (i > 0)
33+
sb.Append(", ");
34+
sb.Append($"(${c++}, ${c++})");
35+
}
36+
sb.Append(" ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
3337
}
3438
else
3539
{

frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbNpgsql.cs

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,23 @@ namespace PlatformBenchmarks
1414
public sealed class RawDb
1515
{
1616
private readonly ConcurrentRandom _random;
17-
private readonly string _connectionString;
1817
private readonly MemoryCache _cache = new(
1918
new MemoryCacheOptions
2019
{
2120
ExpirationScanFrequency = TimeSpan.FromMinutes(60)
2221
});
2322

23+
private readonly NpgsqlDataSource _dataSource;
24+
2425
public RawDb(ConcurrentRandom random, AppSettings appSettings)
2526
{
2627
_random = random;
27-
_connectionString = appSettings.ConnectionString;
28+
_dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString);
2829
}
2930

3031
public async Task<World> LoadSingleQueryRow()
3132
{
32-
using var db = new NpgsqlConnection(_connectionString);
33+
using var db = _dataSource.CreateConnection();
3334
await db.OpenAsync();
3435

3536
var (cmd, _) = CreateReadCommand(db);
@@ -39,20 +40,37 @@ public async Task<World> LoadSingleQueryRow()
3940

4041
public async Task<World[]> LoadMultipleQueriesRows(int count)
4142
{
42-
var result = new World[count];
43+
var results = new World[count];
4344

44-
using var db = new NpgsqlConnection(_connectionString);
45-
await db.OpenAsync();
45+
using var connection = await _dataSource.OpenConnectionAsync();
4646

47-
var (cmd, idParameter) = CreateReadCommand(db);
48-
using var command = cmd;
49-
for (int i = 0; i < result.Length; i++)
47+
using var batch = new NpgsqlBatch(connection)
48+
{
49+
// Inserts a PG Sync message between each statement in the batch, required for compliance with
50+
// TechEmpower general test requirement 7
51+
// https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview
52+
EnableErrorBarriers = true
53+
};
54+
55+
for (var i = 0; i < count; i++)
5056
{
51-
result[i] = await ReadSingleRow(cmd);
52-
idParameter.TypedValue = _random.Next(1, 10001);
57+
batch.BatchCommands.Add(new()
58+
{
59+
CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
60+
Parameters = { new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) } }
61+
});
5362
}
5463

55-
return result;
64+
using var reader = await batch.ExecuteReaderAsync();
65+
66+
for (var i = 0; i < count; i++)
67+
{
68+
await reader.ReadAsync();
69+
results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) };
70+
await reader.NextResultAsync();
71+
}
72+
73+
return results;
5674
}
5775

5876
public Task<CachedWorld[]> LoadCachedQueries(int count)
@@ -79,7 +97,7 @@ public Task<CachedWorld[]> LoadCachedQueries(int count)
7997

8098
static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, RawDb rawdb, CachedWorld[] result)
8199
{
82-
using var db = new NpgsqlConnection(rawdb._connectionString);
100+
using var db = rawdb._dataSource.CreateConnection();
83101
await db.OpenAsync();
84102

85103
var (cmd, idParameter) = rawdb.CreateReadCommand(db);
@@ -109,7 +127,7 @@ static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, R
109127

110128
public async Task PopulateCache()
111129
{
112-
using var db = new NpgsqlConnection(_connectionString);
130+
using var db = _dataSource.CreateConnection();
113131
await db.OpenAsync();
114132

115133
var (cmd, idParameter) = CreateReadCommand(db);
@@ -129,30 +147,43 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
129147
{
130148
var results = new World[count];
131149

132-
using var db = new NpgsqlConnection(_connectionString);
133-
await db.OpenAsync();
150+
using var connection = _dataSource.CreateConnection();
151+
await connection.OpenAsync();
134152

135-
var (queryCmd, queryParameter) = CreateReadCommand(db);
136-
using (queryCmd)
153+
using (var batch = new NpgsqlBatch(connection))
137154
{
138-
for (int i = 0; i < results.Length; i++)
155+
// Inserts a PG Sync message between each statement in the batch, required for compliance with
156+
// TechEmpower general test requirement 7
157+
// https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview
158+
batch.EnableErrorBarriers = true;
159+
160+
for (var i = 0; i < count; i++)
139161
{
140-
results[i] = await ReadSingleRow(queryCmd);
141-
queryParameter.TypedValue = _random.Next(1, 10001);
162+
batch.BatchCommands.Add(new()
163+
{
164+
CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
165+
Parameters = { new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) } }
166+
});
167+
}
168+
169+
using var reader = await batch.ExecuteReaderAsync();
170+
171+
for (var i = 0; i < count; i++)
172+
{
173+
await reader.ReadAsync();
174+
results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) };
175+
await reader.NextResultAsync();
142176
}
143177
}
144178

145-
using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), db))
179+
using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
146180
{
147-
var ids = BatchUpdateString.Ids;
148-
var randoms = BatchUpdateString.Randoms;
149-
150181
for (int i = 0; i < results.Length; i++)
151182
{
152183
var randomNumber = _random.Next(1, 10001);
153184

154-
updateCmd.Parameters.Add(new NpgsqlParameter<int>(parameterName: ids[i], value: results[i].Id));
155-
updateCmd.Parameters.Add(new NpgsqlParameter<int>(parameterName: randoms[i], value: randomNumber));
185+
updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = results[i].Id });
186+
updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = randomNumber });
156187

157188
results[i].RandomNumber = randomNumber;
158189
}
@@ -167,7 +198,7 @@ public async Task<List<Fortune>> LoadFortunesRows()
167198
{
168199
var result = new List<Fortune>();
169200

170-
using (var db = new NpgsqlConnection(_connectionString))
201+
using (var db = _dataSource.CreateConnection())
171202
{
172203
await db.OpenAsync();
173204

frameworks/CSharp/aspnetcore/PlatformBenchmarks/PlatformBenchmarks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
</PropertyGroup>
2323

2424
<ItemGroup>
25-
<PackageReference Condition=" '$(DatabaseProvider)' == 'Npgsql' " Include="Npgsql" Version="6.0.0" />
25+
<PackageReference Condition=" '$(DatabaseProvider)' == 'Npgsql' " Include="Npgsql" Version="7.0.2" />
2626
<PackageReference Condition=" '$(DatabaseProvider)' == 'MySqlConnector' " Include="MySqlConnector" Version="2.0.0" />
2727
</ItemGroup>
2828

0 commit comments

Comments
 (0)