From 21c9f4b8134f241917125e065d4f84ce4d82a566 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 3 Nov 2025 17:01:59 -0800 Subject: [PATCH 1/9] Update .NET version to 10.0 for CSharp/aspnetcore --- frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile | 4 ++-- frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile | 4 ++-- frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile | 4 ++-- frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile | 4 ++-- frameworks/CSharp/aspnetcore/aspnetcore.dockerfile | 4 ++-- frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj | 2 +- frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj | 2 +- frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile index a7396e3b919..3859225dd2a 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile @@ -1,11 +1,11 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build RUN apt-get update RUN apt-get -yqq install clang zlib1g-dev WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql /p:PublishAot=true /p:OptimizationPreference=Speed /p:GarbageCollectionAdaptationMode=0 -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS=http://+:8080 WORKDIR /app diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile index 24893c9717a..96bfb5e1ab4 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Minimal . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile index 6922a53bf2a..4382f7b4b3b 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Mvc . RUN dotnet publish -c Release -o out -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile index ecc0a8331c3..19ff86e3dc9 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=MySqlConnector -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile b/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile index 64510ffe786..4aa5b466752 100644 --- a/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile +++ b/frameworks/CSharp/aspnetcore/aspnetcore.dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /app COPY src/Platform . RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql -FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime ENV URLS=http://+:8080 ENV DOTNET_GCDynamicAdaptationMode=0 ENV DOTNET_ReadyToRun=0 diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj index 12f3446d8b7..fa48fbf0c7c 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable latest diff --git a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj index 68c70002683..08bd22a927a 100644 --- a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj +++ b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable latest diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 7db51dc3ec7..2fd0247b7a7 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 true true preview From e33f111fea51f1a4f8ce1ae16f785871a6066a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Thu, 13 Nov 2025 12:03:49 +0100 Subject: [PATCH 2/9] Update database drivers versions --- frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj | 4 ++-- frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj | 4 ++-- frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj index fa48fbf0c7c..25d89c7f327 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj index 08bd22a927a..8f09807e6f4 100644 --- a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj +++ b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 2fd0247b7a7..23db4ace37e 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -18,9 +18,9 @@ - + - + From c595296d9be86334ef3f5f96553fd2119ecddc17 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 12:05:42 -0800 Subject: [PATCH 3/9] Fix updates --- .../aspnetcore/src/Minimal/Database/Db.cs | 17 +++- .../aspnetcore/src/Minimal/Minimal.csproj | 6 +- .../CSharp/aspnetcore/src/Mvc/Mvc.csproj | 4 +- .../aspnetcore/src/Platform/Data/Random.cs | 31 ------- .../src/Platform/Data/RawDbMySqlConnector.cs | 53 ++++++------ .../src/Platform/Data/RawDbNpgsql.cs | 80 +++++++++---------- .../aspnetcore/src/Platform/Platform.csproj | 8 +- .../CSharp/aspnetcore/src/Platform/Program.cs | 47 ++++++----- 8 files changed, 115 insertions(+), 131 deletions(-) delete mode 100644 frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs index ce23c943abe..2749755458a 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs @@ -63,6 +63,9 @@ public async Task LoadMultipleUpdatesRows(string? parameter) var parameters = new Dictionary(); + var ids = new int[count]; + var numbers = new int[count]; + await using var db = _dbProviderFactory.CreateConnection(); db!.ConnectionString = _connectionString; @@ -72,18 +75,24 @@ public async Task LoadMultipleUpdatesRows(string? parameter) for (var i = 0; i < count; i++) { results[i] = await ReadSingleRow(db); + ids[i] = results[i].Id; } + Array.Sort(ids); + for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001); - parameters[$"@Rn_{i}"] = randomNumber; - parameters[$"@Id_{i}"] = results[i].Id; - results[i].RandomNumber = randomNumber; + numbers[i] = randomNumber; } - await db.ExecuteAsync(BatchUpdateString.Query(count), parameters); + 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"; + + parameters["ids"] = ids; + parameters["newValues"] = numbers; + + await db.ExecuteAsync(update, parameters); return results; } diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj index fa48fbf0c7c..256a58e1de0 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj index 08bd22a927a..4cdddc7c2d6 100644 --- a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj +++ b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs deleted file mode 100644 index a989eb9de2a..00000000000 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/Random.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace PlatformBenchmarks; - -public sealed class ConcurrentRandom -{ - private static int nextSeed = 0; - - // Random isn't thread safe - [ThreadStatic] - private static Random _random; - - private static Random Random => _random ?? CreateRandom(); - - [MethodImpl(MethodImplOptions.NoInlining)] - private static Random CreateRandom() - { - _random = new Random(Interlocked.Increment(ref nextSeed)); - return _random; - } - - public int Next(int minValue, int maxValue) - { - return Random.Next(minValue, maxValue); - } -} diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs index 340fa1236b2..5c7779b70f0 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbMySqlConnector.cs @@ -17,16 +17,14 @@ namespace PlatformBenchmarks; // If you are changing RawDbMySqlConnector.cs, also consider changing RawDbNpgsql.cs. public sealed class RawDb { - private readonly ConcurrentRandom _random; private readonly string _connectionString; private readonly MemoryCache _cache = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) }); private readonly MySqlDataSource _dataSource; - public RawDb(ConcurrentRandom random, AppSettings appSettings) + public RawDb(AppSettings appSettings) { - _random = random; _connectionString = appSettings.ConnectionString; _dataSource = new MySqlDataSource(appSettings.ConnectionString); } @@ -46,10 +44,10 @@ public Task LoadCachedQueries(int count) var result = new CachedWorld[count]; var cacheKeys = _cacheKeys; var cache = _cache; - var random = _random; + for (var i = 0; i < result.Length; i++) { - var id = random.Next(1, 10001); + var id = Random.Shared.Next(1, 10001); var key = cacheKeys[id]; if (cache.TryGetValue(key, out var cached)) { @@ -80,7 +78,7 @@ static async Task LoadUncachedQueries(int id, int i, int count, R { result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - id = rawdb._random.Next(1, 10001); + id = Random.Shared.Next(1, 10001); idParameter.Value = id; key = cacheKeys[id]; } @@ -117,24 +115,18 @@ public async Task LoadMultipleQueriesRows(int count) using var connection = await _dataSource.OpenConnectionAsync(); - using var batch = new MySqlBatch(connection); - - for (var i = 0; i < count; i++) + // It is not acceptable to execute multiple SELECTs within a single complex query. + // It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause. + // Pipelining of network traffic between the application and database is permitted. + + var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection); + using (queryCmd) { - batch.BatchCommands.Add(new MySqlBatchCommand() + for (var i = 0; i < results.Length; i++) { - CommandText = "SELECT id, randomnumber FROM world WHERE id = @id", - Parameters = { new MySqlParameter("@id", _random.Next(1, 10001)) } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); + queryParameter.Value = Random.Shared.Next(1, 10001); + results[i] = await ReadSingleRow(queryCmd); + } } return results; @@ -144,23 +136,34 @@ public async Task LoadMultipleUpdatesRows(int count) { var results = new World[count]; + var ids = new int[count]; + for (var i = 0; i < count; i++) + { + ids[i] = Random.Shared.Next(1, 10001); + } + Array.Sort(ids); + using var connection = await _dataSource.OpenConnectionAsync(); + // Each row must be selected randomly using one query in the same fashion as the single database query test + // Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. + // Similarly, use of a batch or multiple SELECTs within a single statement are not permitted var (queryCmd, queryParameter) = await CreateReadCommandAsync(connection); using (queryCmd) { for (var i = 0; i < results.Length; i++) { + queryParameter.Value = ids[i]; results[i] = await ReadSingleRow(queryCmd); - queryParameter.Value = _random.Next(1, 10001); } } + // MySql doesn't have the unnest function like PostgreSQL, so we have to do a batch update instead using (var updateCmd = new MySqlCommand(BatchUpdateString.Query(count), connection)) { for (var i = 0; i < results.Length; i++) { - var randomNumber = _random.Next(1, 10001); + var randomNumber = Random.Shared.Next(1, 10001); updateCmd.Parameters.AddWithValue($"@Id_{i}", results[i].Id); updateCmd.Parameters.AddWithValue($"@Random_{i}", randomNumber); @@ -204,7 +207,7 @@ public async Task> LoadFortunesRows() private async Task<(MySqlCommand readCmd, MySqlParameter idParameter)> CreateReadCommandAsync(MySqlConnection connection) { var cmd = new MySqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id", connection); - var parameter = new MySqlParameter("@Id", _random.Next(1, 10001)); + var parameter = new MySqlParameter("@Id", Random.Shared.Next(1, 10001)); cmd.Parameters.Add(parameter); diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index 60aeb9bd9a2..8ec04147175 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -10,21 +10,20 @@ using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; using Npgsql; +using NpgsqlTypes; namespace PlatformBenchmarks; public sealed class RawDb { - private readonly ConcurrentRandom _random; private readonly MemoryCache _cache = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) }); private readonly NpgsqlDataSource _dataSource; - public RawDb(ConcurrentRandom random, AppSettings appSettings) + public RawDb(AppSettings appSettings) { - _random = random; - _dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString); + _dataSource = new NpgsqlSlimDataSourceBuilder(appSettings.ConnectionString).EnableArrays().Build(); } public async Task LoadSingleQueryRow() @@ -42,10 +41,10 @@ public Task LoadCachedQueries(int count) var result = new CachedWorld[count]; var cacheKeys = _cacheKeys; var cache = _cache; - var random = _random; + for (var i = 0; i < result.Length; i++) { - var id = random.Next(1, 10001); + var id = Random.Shared.Next(1, 10001); var key = cacheKeys[id]; if (cache.TryGetValue(key, out var cached)) { @@ -76,7 +75,7 @@ static async Task LoadUncachedQueries(int id, int i, int count, R { result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - id = rawdb._random.Next(1, 10001); + id = Random.Shared.Next(1, 10001); idParameter.TypedValue = id; key = cacheKeys[id]; } @@ -109,30 +108,18 @@ public async Task LoadMultipleQueriesRows(int count) using var connection = await _dataSource.OpenConnectionAsync(); - using var batch = new NpgsqlBatch(connection) - { - // Inserts a PG Sync message between each statement in the batch, required for compliance with - // TechEmpower general test requirement 7 - // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview - EnableErrorBarriers = true - }; - - for (var i = 0; i < count; i++) + // It is not acceptable to execute multiple SELECTs within a single complex query. + // It is not acceptable to retrieve all required rows using a SELECT ... WHERE id IN (...) clause. + // Pipelining of network traffic between the application and database is permitted. + + var (queryCmd, queryParameter) = CreateReadCommand(connection); + using (queryCmd) { - batch.BatchCommands.Add(new() + for (var i = 0; i < results.Length; i++) { - CommandText = "SELECT id, randomnumber FROM world WHERE id = $1", - Parameters = { new NpgsqlParameter { TypedValue = _random.Next(1, 10001) } } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); + queryParameter.TypedValue = Random.Shared.Next(1, 10001); + results[i] = await ReadSingleRow(queryCmd); + } } return results; @@ -142,33 +129,44 @@ public async Task LoadMultipleUpdatesRows(int count) { var results = new World[count]; + var ids = new int[count]; + for (var i = 0; i < count; i++) + { + ids[i] = Random.Shared.Next(1, 10001); + } + Array.Sort(ids); + using var connection = CreateConnection(); await connection.OpenAsync(); + // Each row must be selected randomly using one query in the same fashion as the single database query test + // Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. + // Similarly, use of a batch or multiple SELECTs within a single statement are not permitted var (queryCmd, queryParameter) = CreateReadCommand(connection); using (queryCmd) { for (var i = 0; i < results.Length; i++) { + queryParameter.TypedValue = ids[i]; results[i] = await ReadSingleRow(queryCmd); - queryParameter.TypedValue = _random.Next(1, 10001); } } - using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection)) + var numbers = new int[count]; + for (var i = 0; i < count; i++) { - for (var i = 0; i < results.Length; i++) - { - var randomNumber = _random.Next(1, 10001); + var randomNumber = Random.Shared.Next(1, 10001); + results[i].RandomNumber = randomNumber; + numbers[i] = randomNumber; + } - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = results[i].Id }); - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = randomNumber }); + 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"; - results[i].RandomNumber = randomNumber; - } + using var updateCmd = new NpgsqlCommand(update, connection); + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = ids, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer }); + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = numbers, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer }); - await updateCmd.ExecuteNonQueryAsync(); - } + await updateCmd.ExecuteNonQueryAsync(); return results; } @@ -203,7 +201,7 @@ public async Task> LoadFortunesRows() private (NpgsqlCommand readCmd, NpgsqlParameter idParameter) CreateReadCommand(NpgsqlConnection connection) { var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection); - var parameter = new NpgsqlParameter { TypedValue = _random.Next(1, 10001) }; + var parameter = new NpgsqlParameter { TypedValue = Random.Shared.Next(1, 10001) }; cmd.Parameters.Add(parameter); diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 2fd0247b7a7..46911b46548 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -18,10 +18,10 @@ - - - - + + + + diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Program.cs b/frameworks/CSharp/aspnetcore/src/Platform/Program.cs index 28fc5d757dd..7877351f2da 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Program.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Program.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; namespace PlatformBenchmarks; @@ -42,7 +43,7 @@ public static async Task Main(string[] args) await host.RunAsync(); } - public static IWebHost BuildWebHost(string[] args) + public static IHost BuildWebHost(string[] args) { Console.WriteLine($"BuildWebHost()"); Console.WriteLine($"Args: {string.Join(' ', args)}"); @@ -59,30 +60,34 @@ public static IWebHost BuildWebHost(string[] args) var appSettings = config.Get(); Console.WriteLine($"ConnectionString: {appSettings.ConnectionString}"); - BenchmarkApplication.RawDb = new RawDb(new ConcurrentRandom(), appSettings); + BenchmarkApplication.RawDb = new RawDb(appSettings); - var hostBuilder = new WebHostBuilder() - .UseBenchmarksConfiguration(config) - .UseKestrel((context, options) => + var hostBuilder = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - var endPoint = context.Configuration.CreateIPEndPoint(); - - options.Listen(endPoint, builder => + webHostBuilder + .UseBenchmarksConfiguration(config) + .UseKestrel((context, options) => + { + var endPoint = context.Configuration.CreateIPEndPoint(); + + options.Listen(endPoint, builder => + { + builder.UseHttpApplication(); + }); + }) + .UseStartup(); + + webHostBuilder.UseSockets(options => { - builder.UseHttpApplication(); - }); - }) - .UseStartup(); - - hostBuilder.UseSockets(options => - { - options.WaitForDataBeforeAllocatingBuffer = false; + options.WaitForDataBeforeAllocatingBuffer = false; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - options.UnsafePreferInlineScheduling = true; - } - }); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + options.UnsafePreferInlineScheduling = true; + } + }); + }); var host = hostBuilder.Build(); From d351a4f3fcc8f3437c165e6ae780ed78baf9f874 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 12:19:38 -0800 Subject: [PATCH 4/9] Try older npgsql --- frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 46911b46548..3f81c969cb6 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -18,7 +18,7 @@ - + From 64ad7a7bda751c3ce933aa80b19da27ae5a65b08 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 12:23:29 -0800 Subject: [PATCH 5/9] Only run "updates" and "queries" --- .../CSharp/aspnetcore/benchmark_config.json | 95 -------------- .../aspnetcore/benchmark_config_backup.json | 121 ++++++++++++++++++ .../aspnetcore/src/Platform/Platform.csproj | 2 +- 3 files changed, 122 insertions(+), 96 deletions(-) create mode 100644 frameworks/CSharp/aspnetcore/benchmark_config_backup.json diff --git a/frameworks/CSharp/aspnetcore/benchmark_config.json b/frameworks/CSharp/aspnetcore/benchmark_config.json index eb56fddfb57..0e6389e3bfd 100644 --- a/frameworks/CSharp/aspnetcore/benchmark_config.json +++ b/frameworks/CSharp/aspnetcore/benchmark_config.json @@ -4,13 +4,8 @@ "tests": [ { "default": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", "query_url": "/queries/", - "fortune_url": "/fortunes", "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", "port": 8080, "approach": "Realistic", "classification": "Platform", @@ -25,96 +20,6 @@ "database_os": "Linux", "display_name": "ASP.NET Core [Platform]", "notes": "" - }, - "aot": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "framework": "ASP.NET Core [Platform]", - "language": "C#", - "orm": "Raw", - "platform": ".NET", - "flavor": "NativeAOT", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Platform, AOT]", - "notes": "" - }, - "minimal": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "Postgres", - "framework": "ASP.NET Core [Minimal APIs]", - "language": "C#", - "orm": "Micro", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Minimal APIs]", - "notes": "", - "versus": "aspnetcore" - }, - "mvc": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "ASP.NET Core [MVC]", - "language": "C#", - "orm": "Full", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [MVC]", - "notes": "", - "versus": "aspnetcore" - }, - "mysql": { - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MySQL", - "framework": "ASP.NET Core [Platform]", - "language": "C#", - "orm": "Raw", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Platform, MySQL]", - "notes": "", - "versus": "aspnetcore" } } ] diff --git a/frameworks/CSharp/aspnetcore/benchmark_config_backup.json b/frameworks/CSharp/aspnetcore/benchmark_config_backup.json new file mode 100644 index 00000000000..eb56fddfb57 --- /dev/null +++ b/frameworks/CSharp/aspnetcore/benchmark_config_backup.json @@ -0,0 +1,121 @@ +{ + "framework": "aspnetcore", + "maintainers": ["DamianEdwards", "sebastienros"], + "tests": [ + { + "default": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "ASP.NET Core [Platform]", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Platform]", + "notes": "" + }, + "aot": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "ASP.NET Core [Platform]", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "flavor": "NativeAOT", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Platform, AOT]", + "notes": "" + }, + "minimal": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "ASP.NET Core [Minimal APIs]", + "language": "C#", + "orm": "Micro", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Minimal APIs]", + "notes": "", + "versus": "aspnetcore" + }, + "mvc": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "Postgres", + "framework": "ASP.NET Core [MVC]", + "language": "C#", + "orm": "Full", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [MVC]", + "notes": "", + "versus": "aspnetcore" + }, + "mysql": { + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "MySQL", + "framework": "ASP.NET Core [Platform]", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Platform, MySQL]", + "notes": "", + "versus": "aspnetcore" + } + } + ] +} diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj index 3f81c969cb6..46911b46548 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj +++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj @@ -18,7 +18,7 @@ - + From b79fdcfe9d979e8bcc8993bc31f0bcafcd584362 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 15:46:23 -0800 Subject: [PATCH 6/9] Ensure there are no updated ids duplicated --- .../CSharp/aspnetcore/benchmark_config.json | 95 ++++++++++++++ .../aspnetcore/benchmark_config_backup.json | 121 ------------------ .../aspnetcore/src/Minimal/Database/Db.cs | 6 +- .../src/Platform/Data/RawDbNpgsql.cs | 5 + 4 files changed, 105 insertions(+), 122 deletions(-) delete mode 100644 frameworks/CSharp/aspnetcore/benchmark_config_backup.json diff --git a/frameworks/CSharp/aspnetcore/benchmark_config.json b/frameworks/CSharp/aspnetcore/benchmark_config.json index 0e6389e3bfd..eb56fddfb57 100644 --- a/frameworks/CSharp/aspnetcore/benchmark_config.json +++ b/frameworks/CSharp/aspnetcore/benchmark_config.json @@ -4,8 +4,13 @@ "tests": [ { "default": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", "query_url": "/queries/", + "fortune_url": "/fortunes", "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", "port": 8080, "approach": "Realistic", "classification": "Platform", @@ -20,6 +25,96 @@ "database_os": "Linux", "display_name": "ASP.NET Core [Platform]", "notes": "" + }, + "aot": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "ASP.NET Core [Platform]", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "flavor": "NativeAOT", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Platform, AOT]", + "notes": "" + }, + "minimal": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "ASP.NET Core [Minimal APIs]", + "language": "C#", + "orm": "Micro", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Minimal APIs]", + "notes": "", + "versus": "aspnetcore" + }, + "mvc": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "Postgres", + "framework": "ASP.NET Core [MVC]", + "language": "C#", + "orm": "Full", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [MVC]", + "notes": "", + "versus": "aspnetcore" + }, + "mysql": { + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "cached_query_url": "/cached-worlds/", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "MySQL", + "framework": "ASP.NET Core [Platform]", + "language": "C#", + "orm": "Raw", + "platform": ".NET", + "flavor": "CoreCLR", + "webserver": "Kestrel", + "os": "Linux", + "database_os": "Linux", + "display_name": "ASP.NET Core [Platform, MySQL]", + "notes": "", + "versus": "aspnetcore" } } ] diff --git a/frameworks/CSharp/aspnetcore/benchmark_config_backup.json b/frameworks/CSharp/aspnetcore/benchmark_config_backup.json deleted file mode 100644 index eb56fddfb57..00000000000 --- a/frameworks/CSharp/aspnetcore/benchmark_config_backup.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "framework": "aspnetcore", - "maintainers": ["DamianEdwards", "sebastienros"], - "tests": [ - { - "default": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "framework": "ASP.NET Core [Platform]", - "language": "C#", - "orm": "Raw", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Platform]", - "notes": "" - }, - "aot": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "framework": "ASP.NET Core [Platform]", - "language": "C#", - "orm": "Raw", - "platform": ".NET", - "flavor": "NativeAOT", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Platform, AOT]", - "notes": "" - }, - "minimal": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "Postgres", - "framework": "ASP.NET Core [Minimal APIs]", - "language": "C#", - "orm": "Micro", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Minimal APIs]", - "notes": "", - "versus": "aspnetcore" - }, - "mvc": { - "plaintext_url": "/plaintext", - "json_url": "/json", - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "ASP.NET Core [MVC]", - "language": "C#", - "orm": "Full", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [MVC]", - "notes": "", - "versus": "aspnetcore" - }, - "mysql": { - "db_url": "/db", - "query_url": "/queries/", - "fortune_url": "/fortunes", - "update_url": "/updates/", - "cached_query_url": "/cached-worlds/", - "port": 8080, - "approach": "Realistic", - "classification": "Platform", - "database": "MySQL", - "framework": "ASP.NET Core [Platform]", - "language": "C#", - "orm": "Raw", - "platform": ".NET", - "flavor": "CoreCLR", - "webserver": "Kestrel", - "os": "Linux", - "database_os": "Linux", - "display_name": "ASP.NET Core [Platform, MySQL]", - "notes": "", - "versus": "aspnetcore" - } - } - ] -} diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs index 2749755458a..44f2eabf599 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs @@ -77,9 +77,13 @@ public async Task LoadMultipleUpdatesRows(string? parameter) results[i] = await ReadSingleRow(db); ids[i] = results[i].Id; } - Array.Sort(ids); + // Ensure unique ids by incrementing duplicates + for (var i = 1; i < count; i++) + if (ids[i] <= ids[i - 1]) + ids[i] = Math.Min(ids[i - 1] + 1, 10000); + for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001); diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index 8ec04147175..6e27ed3705e 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -136,6 +136,11 @@ public async Task LoadMultipleUpdatesRows(int count) } Array.Sort(ids); + // Ensure unique ids by incrementing duplicates + for (var i = 1; i < count; i++) + if (ids[i] <= ids[i - 1]) + ids[i] = Math.Min(ids[i - 1] + 1, 10000); + using var connection = CreateConnection(); await connection.OpenAsync(); From b79acb7b65d3c6c1f31c23512fde7bd90a2aa003 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 17:21:22 -0800 Subject: [PATCH 7/9] Prevent collisions --- .../CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index 6e27ed3705e..8d51c2e17bd 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -161,6 +161,11 @@ public async Task LoadMultipleUpdatesRows(int count) for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001); + if (results[i].RandomNumber == randomNumber) + { + randomNumber = (randomNumber % 10000) + 1; + } + results[i].RandomNumber = randomNumber; numbers[i] = randomNumber; } From 5ee64be92023139c6b86eb365ff6e0da8ccd0026 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 18:16:19 -0800 Subject: [PATCH 8/9] Update connection string --- frameworks/CSharp/aspnetcore/appsettings.postgresql.json | 2 +- .../CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/frameworks/CSharp/aspnetcore/appsettings.postgresql.json b/frameworks/CSharp/aspnetcore/appsettings.postgresql.json index 423af4d19b0..897abdcd96f 100644 --- a/frameworks/CSharp/aspnetcore/appsettings.postgresql.json +++ b/frameworks/CSharp/aspnetcore/appsettings.postgresql.json @@ -1,4 +1,4 @@ { - "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4", + "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000;", "Database": "postgresql" } diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index 8d51c2e17bd..a39a53b7b2b 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -138,11 +138,10 @@ public async Task LoadMultipleUpdatesRows(int count) // Ensure unique ids by incrementing duplicates for (var i = 1; i < count; i++) - if (ids[i] <= ids[i - 1]) - ids[i] = Math.Min(ids[i - 1] + 1, 10000); + if (ids[i] == ids[i - 1]) + ids[i] = (ids[i] % 10000) + 1; - using var connection = CreateConnection(); - await connection.OpenAsync(); + using var connection = await _dataSource.OpenConnectionAsync(); // Each row must be selected randomly using one query in the same fashion as the single database query test // Use of IN clauses or similar means to consolidate multiple queries into one operation is not permitted. From 230f1e93a2a846ba30dbe465b2dbcaf34d312b30 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 26 Nov 2025 18:33:45 -0800 Subject: [PATCH 9/9] Sync code --- frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs | 9 +++++++-- .../CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs index 44f2eabf599..09ea9e26ce6 100644 --- a/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs +++ b/frameworks/CSharp/aspnetcore/src/Minimal/Database/Db.cs @@ -81,12 +81,17 @@ public async Task LoadMultipleUpdatesRows(string? parameter) // Ensure unique ids by incrementing duplicates for (var i = 1; i < count; i++) - if (ids[i] <= ids[i - 1]) - ids[i] = Math.Min(ids[i - 1] + 1, 10000); + if (ids[i] == ids[i - 1]) + ids[i] = (ids[i] % 10000) + 1; for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001); + if (results[i].RandomNumber == randomNumber) + { + randomNumber = (randomNumber % 10000) + 1; + } + results[i].RandomNumber = randomNumber; numbers[i] = randomNumber; } diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs index a39a53b7b2b..e8e05ab34e9 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/Data/RawDbNpgsql.cs @@ -130,6 +130,8 @@ public async Task LoadMultipleUpdatesRows(int count) var results = new World[count]; var ids = new int[count]; + var numbers = new int[count]; + for (var i = 0; i < count; i++) { ids[i] = Random.Shared.Next(1, 10001); @@ -156,7 +158,6 @@ public async Task LoadMultipleUpdatesRows(int count) } } - var numbers = new int[count]; for (var i = 0; i < count; i++) { var randomNumber = Random.Shared.Next(1, 10001);