Skip to content

Commit c595296

Browse files
committed
Fix updates
1 parent 21c9f4b commit c595296

File tree

8 files changed

+115
-131
lines changed

8 files changed

+115
-131
lines changed

frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ public async Task<World[]> LoadMultipleUpdatesRows(string? parameter)
6363

6464
var parameters = new Dictionary<string, object>();
6565

66+
var ids = new int[count];
67+
var numbers = new int[count];
68+
6669
await using var db = _dbProviderFactory.CreateConnection();
6770

6871
db!.ConnectionString = _connectionString;
@@ -72,18 +75,24 @@ public async Task<World[]> LoadMultipleUpdatesRows(string? parameter)
7275
for (var i = 0; i < count; i++)
7376
{
7477
results[i] = await ReadSingleRow(db);
78+
ids[i] = results[i].Id;
7579
}
7680

81+
Array.Sort(ids);
82+
7783
for (var i = 0; i < count; i++)
7884
{
7985
var randomNumber = Random.Shared.Next(1, 10001);
80-
parameters[$"@Rn_{i}"] = randomNumber;
81-
parameters[$"@Id_{i}"] = results[i].Id;
82-
8386
results[i].RandomNumber = randomNumber;
87+
numbers[i] = randomNumber;
8488
}
8589

86-
await db.ExecuteAsync(BatchUpdateString.Query(count), parameters);
90+
var update = "UPDATE world w SET randomnumber = u.new_val FROM (SELECT unnest(@ids) as id, unnest(@newValues) as new_val) u WHERE w.id = u.id";
91+
92+
parameters["ids"] = ids;
93+
parameters["newValues"] = numbers;
94+
95+
await db.ExecuteAsync(update, parameters);
8796
return results;
8897
}
8998

frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Npgsql" Version="9.0.2" />
13-
<PackageReference Include="Dapper" Version="2.1.35" />
14-
<PackageReference Include="RazorSlices" Version="0.8.1" />
12+
<PackageReference Include="Npgsql" Version="10.0.0" />
13+
<PackageReference Include="Dapper" Version="2.1.66" />
14+
<PackageReference Include="RazorSlices" Version="0.9.5" />
1515
</ItemGroup>
1616

1717
</Project>

frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Npgsql" Version="9.0.2" />
13-
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
12+
<PackageReference Include="Npgsql" Version="10.0.0" />
13+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
1414
</ItemGroup>
1515

1616
</Project>

frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ namespace PlatformBenchmarks;
1717
// If you are changing RawDbMySqlConnector.cs, also consider changing RawDbNpgsql.cs.
1818
public sealed class RawDb
1919
{
20-
private readonly ConcurrentRandom _random;
2120
private readonly string _connectionString;
2221
private readonly MemoryCache _cache
2322
= new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });
2423

2524
private readonly MySqlDataSource _dataSource;
2625

27-
public RawDb(ConcurrentRandom random, AppSettings appSettings)
26+
public RawDb(AppSettings appSettings)
2827
{
29-
_random = random;
3028
_connectionString = appSettings.ConnectionString;
3129
_dataSource = new MySqlDataSource(appSettings.ConnectionString);
3230
}
@@ -46,10 +44,10 @@ public Task<CachedWorld[]> LoadCachedQueries(int count)
4644
var result = new CachedWorld[count];
4745
var cacheKeys = _cacheKeys;
4846
var cache = _cache;
49-
var random = _random;
47+
5048
for (var i = 0; i < result.Length; i++)
5149
{
52-
var id = random.Next(1, 10001);
50+
var id = Random.Shared.Next(1, 10001);
5351
var key = cacheKeys[id];
5452
if (cache.TryGetValue(key, out var cached))
5553
{
@@ -80,7 +78,7 @@ static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, R
8078
{
8179
result[i] = await rawdb._cache.GetOrCreateAsync(key, create);
8280

83-
id = rawdb._random.Next(1, 10001);
81+
id = Random.Shared.Next(1, 10001);
8482
idParameter.Value = id;
8583
key = cacheKeys[id];
8684
}
@@ -117,24 +115,18 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
117115

118116
using var connection = await _dataSource.OpenConnectionAsync();
119117

120-
using var batch = new MySqlBatch(connection);
121-
122-
for (var i = 0; i < count; i++)
118+
// It is not acceptable to execute multiple SELECTs within a single complex query.
119+
// It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause.
120+
// Pipelining of network traffic between the application and database is permitted.
121+
122+
var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection);
123+
using (queryCmd)
123124
{
124-
batch.BatchCommands.Add(new MySqlBatchCommand()
125+
for (var i = 0; i < results.Length; i++)
125126
{
126-
CommandText = "SELECT id, randomnumber FROM world WHERE id = @id",
127-
Parameters = { new MySqlParameter("@id", _random.Next(1, 10001)) }
128-
});
129-
}
130-
131-
using var reader = await batch.ExecuteReaderAsync();
132-
133-
for (var i = 0; i < count; i++)
134-
{
135-
await reader.ReadAsync();
136-
results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) };
137-
await reader.NextResultAsync();
127+
queryParameter.Value = Random.Shared.Next(1, 10001);
128+
results[i] = await ReadSingleRow(queryCmd);
129+
}
138130
}
139131

140132
return results;
@@ -144,23 +136,34 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
144136
{
145137
var results = new World[count];
146138

139+
var ids = new int[count];
140+
for (var i = 0; i < count; i++)
141+
{
142+
ids[i] = Random.Shared.Next(1, 10001);
143+
}
144+
Array.Sort(ids);
145+
147146
using var connection = await _dataSource.OpenConnectionAsync();
148147

148+
// Each row must be selected randomly using one query in the same fashion as the single database query test
149+
// Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted.
150+
// Similarly, use of a batch or multiple SELECTs within a single statement are not permitted
149151
var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection);
150152
using (queryCmd)
151153
{
152154
for (var i = 0; i < results.Length; i++)
153155
{
156+
queryParameter.Value = ids[i];
154157
results[i] = await ReadSingleRow(queryCmd);
155-
queryParameter.Value = _random.Next(1, 10001);
156158
}
157159
}
158160

161+
// MySql doesn't have the unnest function like PostgreSQL, so we have to do a batch update instead
159162
using (var updateCmd = new MySqlCommand(BatchUpdateString.Query(count), connection))
160163
{
161164
for (var i = 0; i < results.Length; i++)
162165
{
163-
var randomNumber = _random.Next(1, 10001);
166+
var randomNumber = Random.Shared.Next(1, 10001);
164167

165168
updateCmd.Parameters.AddWithValue($"@Id_{i}", results[i].Id);
166169
updateCmd.Parameters.AddWithValue($"@Random_{i}", randomNumber);
@@ -204,7 +207,7 @@ public async Task<List<FortuneUtf16>> LoadFortunesRows()
204207
private async Task<(MySqlCommand readCmd, MySqlParameter idParameter)> CreateReadCommandAsync(MySqlConnection connection)
205208
{
206209
var cmd = new MySqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id", connection);
207-
var parameter = new MySqlParameter("@Id", _random.Next(1, 10001));
210+
var parameter = new MySqlParameter("@Id", Random.Shared.Next(1, 10001));
208211

209212
cmd.Parameters.Add(parameter);
210213

frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,20 @@
1010
using System.Threading.Tasks;
1111
using Microsoft.Extensions.Caching.Memory;
1212
using Npgsql;
13+
using NpgsqlTypes;
1314

1415
namespace PlatformBenchmarks;
1516

1617
public sealed class RawDb
1718
{
18-
private readonly ConcurrentRandom _random;
1919
private readonly MemoryCache _cache
2020
= new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });
2121

2222
private readonly NpgsqlDataSource _dataSource;
2323

24-
public RawDb(ConcurrentRandom random, AppSettings appSettings)
24+
public RawDb(AppSettings appSettings)
2525
{
26-
_random = random;
27-
_dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString);
26+
_dataSource = new NpgsqlSlimDataSourceBuilder(appSettings.ConnectionString).EnableArrays().Build();
2827
}
2928

3029
public async Task<World> LoadSingleQueryRow()
@@ -42,10 +41,10 @@ public Task<CachedWorld[]> LoadCachedQueries(int count)
4241
var result = new CachedWorld[count];
4342
var cacheKeys = _cacheKeys;
4443
var cache = _cache;
45-
var random = _random;
44+
4645
for (var i = 0; i < result.Length; i++)
4746
{
48-
var id = random.Next(1, 10001);
47+
var id = Random.Shared.Next(1, 10001);
4948
var key = cacheKeys[id];
5049
if (cache.TryGetValue(key, out var cached))
5150
{
@@ -76,7 +75,7 @@ static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, R
7675
{
7776
result[i] = await rawdb._cache.GetOrCreateAsync(key, create);
7877

79-
id = rawdb._random.Next(1, 10001);
78+
id = Random.Shared.Next(1, 10001);
8079
idParameter.TypedValue = id;
8180
key = cacheKeys[id];
8281
}
@@ -109,30 +108,18 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
109108

110109
using var connection = await _dataSource.OpenConnectionAsync();
111110

112-
using var batch = new NpgsqlBatch(connection)
113-
{
114-
// Inserts a PG Sync message between each statement in the batch, required for compliance with
115-
// TechEmpower general test requirement 7
116-
// https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview
117-
EnableErrorBarriers = true
118-
};
119-
120-
for (var i = 0; i < count; i++)
111+
// It is not acceptable to execute multiple SELECTs within a single complex query.
112+
// It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause.
113+
// Pipelining of network traffic between the application and database is permitted.
114+
115+
var (queryCmd, queryParameter) = CreateReadCommand(connection);
116+
using (queryCmd)
121117
{
122-
batch.BatchCommands.Add(new()
118+
for (var i = 0; i < results.Length; i++)
123119
{
124-
CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
125-
Parameters = { new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) } }
126-
});
127-
}
128-
129-
using var reader = await batch.ExecuteReaderAsync();
130-
131-
for (var i = 0; i < count; i++)
132-
{
133-
await reader.ReadAsync();
134-
results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) };
135-
await reader.NextResultAsync();
120+
queryParameter.TypedValue = Random.Shared.Next(1, 10001);
121+
results[i] = await ReadSingleRow(queryCmd);
122+
}
136123
}
137124

138125
return results;
@@ -142,33 +129,44 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
142129
{
143130
var results = new World[count];
144131

132+
var ids = new int[count];
133+
for (var i = 0; i < count; i++)
134+
{
135+
ids[i] = Random.Shared.Next(1, 10001);
136+
}
137+
Array.Sort(ids);
138+
145139
using var connection = CreateConnection();
146140
await connection.OpenAsync();
147141

142+
// Each row must be selected randomly using one query in the same fashion as the single database query test
143+
// Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted.
144+
// Similarly, use of a batch or multiple SELECTs within a single statement are not permitted
148145
var (queryCmd, queryParameter) = CreateReadCommand(connection);
149146
using (queryCmd)
150147
{
151148
for (var i = 0; i < results.Length; i++)
152149
{
150+
queryParameter.TypedValue = ids[i];
153151
results[i] = await ReadSingleRow(queryCmd);
154-
queryParameter.TypedValue = _random.Next(1, 10001);
155152
}
156153
}
157154

158-
using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
155+
var numbers = new int[count];
156+
for (var i = 0; i < count; i++)
159157
{
160-
for (var i = 0; i < results.Length; i++)
161-
{
162-
var randomNumber = _random.Next(1, 10001);
158+
var randomNumber = Random.Shared.Next(1, 10001);
159+
results[i].RandomNumber = randomNumber;
160+
numbers[i] = randomNumber;
161+
}
163162

164-
updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = results[i].Id });
165-
updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = randomNumber });
163+
var update = "UPDATE world w SET randomnumber = u.new_val FROM (SELECT unnest($1) as id, unnest($2) as new_val) u WHERE w.id = u.id";
166164

167-
results[i].RandomNumber = randomNumber;
168-
}
165+
using var updateCmd = new NpgsqlCommand(update, connection);
166+
updateCmd.Parameters.Add(new NpgsqlParameter<int[]> { TypedValue = ids, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer });
167+
updateCmd.Parameters.Add(new NpgsqlParameter<int[]> { TypedValue = numbers, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer });
169168

170-
await updateCmd.ExecuteNonQueryAsync();
171-
}
169+
await updateCmd.ExecuteNonQueryAsync();
172170

173171
return results;
174172
}
@@ -203,7 +201,7 @@ public async Task<List<FortuneUtf8>> LoadFortunesRows()
203201
private (NpgsqlCommand readCmd, NpgsqlParameter<int> idParameter) CreateReadCommand(NpgsqlConnection connection)
204202
{
205203
var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection);
206-
var parameter = new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) };
204+
var parameter = new NpgsqlParameter<int> { TypedValue = Random.Shared.Next(1, 10001) };
207205

208206
cmd.Parameters.Add(parameter);
209207

frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
</ItemGroup>
1919

2020
<ItemGroup>
21-
<PackageReference Include="Npgsql" Version="9.0.2" />
22-
<PackageReference Include="MySqlConnector" Version="2.3.7" />
23-
<PackageReference Include="Dapper" Version="2.1.35" />
24-
<PackageReference Include="RazorSlices" Version="0.8.1" />
21+
<PackageReference Include="Npgsql" Version="10.0.0" />
22+
<PackageReference Include="MySqlConnector" Version="2.5.0" />
23+
<PackageReference Include="Dapper" Version="2.1.66" />
24+
<PackageReference Include="RazorSlices" Version="0.9.5" />
2525
</ItemGroup>
2626

2727
<ItemGroup Condition="$(PublishAot) == 'true'">

0 commit comments

Comments
 (0)