Skip to content

Commit 4d3d2c6

Browse files
konardclaude
andcommitted
Add PostgreSQL comparison with Npgsql.EntityFrameworkCore.PostgreSQL
This commit adds PostgreSQL support to the comparison benchmarks alongside SQLite and Doublets. The implementation includes: - Added Npgsql.EntityFrameworkCore.PostgreSQL package dependency - Created PostgreSQL namespace with PostgreSQLDbContext and PostgreSQLTestRun - Updated benchmark configuration to include PostgreSQL benchmarks - Updated Program.cs to include PostgreSQL in manual comparisons - Upgraded target framework to .NET 7.0 for compatibility The PostgreSQL implementation follows the same patterns as the SQLite implementation, allowing for consistent performance comparisons across all three data storage approaches. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 5dec019 commit 4d3d2c6

5 files changed

Lines changed: 200 additions & 1 deletion

File tree

Benchmarks.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using BenchmarkDotNet.Configs;
44
using Comparisons.SQLiteVSDoublets.Model;
55
using Comparisons.SQLiteVSDoublets.SQLite;
6+
using Comparisons.SQLiteVSDoublets.PostgreSQL;
67
using Comparisons.SQLiteVSDoublets.Doublets;
78

89
namespace Comparisons.SQLiteVSDoublets
@@ -22,13 +23,15 @@ private class Config : ManualConfig
2223
[Params(1000, 10000, 100000)]
2324
public int N;
2425
private SQLiteTestRun _sqliteTestRun;
26+
private PostgreSQLTestRun _postgresqlTestRun;
2527
private DoubletsTestRun _doubletsTestRun;
2628

2729
[GlobalSetup]
2830
public void Setup()
2931
{
3032
BlogPosts.GenerateData(N);
3133
_sqliteTestRun = new SQLiteTestRun("test.db");
34+
_postgresqlTestRun = new PostgreSQLTestRun("Host=localhost;Database=test;Username=test;Password=test");
3235
_doubletsTestRun = new DoubletsTestRun("test.links");
3336
}
3437

@@ -42,6 +45,16 @@ public void SQLiteOutput()
4245
File.WriteAllText(Path.Combine(SizeAfterCreationColumn.DbSizeOutputFolder, $"disk-size.sqlite.{N}.txt"), _sqliteTestRun.Results.DbSizeAfterCreation.ToString());
4346
}
4447

48+
[Benchmark]
49+
public void PostgreSQL() => _postgresqlTestRun.Run();
50+
51+
[IterationCleanup(Target = "PostgreSQL")]
52+
public void PostgreSQLOutput()
53+
{
54+
Directory.CreateDirectory(SizeAfterCreationColumn.DbSizeOutputFolder);
55+
File.WriteAllText(Path.Combine(SizeAfterCreationColumn.DbSizeOutputFolder, $"disk-size.postgresql.{N}.txt"), _postgresqlTestRun.Results.DbSizeAfterCreation.ToString());
56+
}
57+
4558
[Benchmark]
4659
public void Doublets() => _doubletsTestRun.Run();
4760

Comparisons.SQLiteVSDoublets.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6</TargetFramework>
5+
<TargetFramework>net7.0</TargetFramework>
66
<Nullable>enable</Nullable>
77
</PropertyGroup>
88

99
<ItemGroup>
1010
<PackageReference Include="BenchmarkDotNet" Version="0.13.6" />
1111
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.9" />
12+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
1213
<PackageReference Include="Platform.Diagnostics" Version="0.1.0" />
1314
</ItemGroup>
1415

PostgreSQL/PostgreSQLDbContext.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.Reflection;
2+
using Microsoft.EntityFrameworkCore;
3+
using Comparisons.SQLiteVSDoublets.Model;
4+
5+
namespace Comparisons.SQLiteVSDoublets.PostgreSQL
6+
{
7+
/// <summary>
8+
/// <para>
9+
/// Represents the PostgreSQL db context.
10+
/// </para>
11+
/// <para></para>
12+
/// </summary>
13+
/// <seealso cref="DbContext"/>
14+
public class PostgreSQLDbContext : DbContext
15+
{
16+
/// <summary>
17+
/// <para>
18+
/// The connection string.
19+
/// </para>
20+
/// <para></para>
21+
/// </summary>
22+
private readonly string _connectionString;
23+
24+
/// <summary>
25+
/// <para>
26+
/// Gets or sets the blog posts value.
27+
/// </para>
28+
/// <para></para>
29+
/// </summary>
30+
public DbSet<BlogPost> BlogPosts { get; set; }
31+
32+
/// <summary>
33+
/// <para>
34+
/// Initializes a new <see cref="PostgreSQLDbContext"/> instance.
35+
/// </para>
36+
/// <para></para>
37+
/// </summary>
38+
/// <param name="connectionString">
39+
/// <para>A connection string.</para>
40+
/// <para></para>
41+
/// </param>
42+
public PostgreSQLDbContext(string connectionString) => _connectionString = connectionString;
43+
44+
/// <summary>
45+
/// <para>
46+
/// Ons the configuring using the specified options builder.
47+
/// </para>
48+
/// <para></para>
49+
/// </summary>
50+
/// <param name="optionsBuilder">
51+
/// <para>The options builder.</para>
52+
/// <para></para>
53+
/// </param>
54+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
55+
{
56+
optionsBuilder.UseNpgsql(_connectionString, options =>
57+
{
58+
options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
59+
});
60+
base.OnConfiguring(optionsBuilder);
61+
}
62+
63+
/// <summary>
64+
/// <para>
65+
/// Ons the model creating using the specified model builder.
66+
/// </para>
67+
/// <para></para>
68+
/// </summary>
69+
/// <param name="modelBuilder">
70+
/// <para>The model builder.</para>
71+
/// <para></para>
72+
/// </param>
73+
protected override void OnModelCreating(ModelBuilder modelBuilder)
74+
{
75+
modelBuilder.Entity<BlogPost>().ToTable("BlogPosts", "test");
76+
modelBuilder.Entity<BlogPost>(entity =>
77+
{
78+
entity.HasKey(e => e.Id);
79+
entity.HasIndex(e => e.Title).IsUnique();
80+
entity.Property(e => e.PublicationDateTime).HasDefaultValueSql("CURRENT_TIMESTAMP");
81+
});
82+
base.OnModelCreating(modelBuilder);
83+
}
84+
}
85+
}

PostgreSQL/PostgreSQLTestRun.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Linq;
2+
using Comparisons.SQLiteVSDoublets.Model;
3+
4+
namespace Comparisons.SQLiteVSDoublets.PostgreSQL
5+
{
6+
/// <summary>
7+
/// <para>
8+
/// Represents the PostgreSQL test run.
9+
/// </para>
10+
/// <para></para>
11+
/// </summary>
12+
/// <seealso cref="TestRun"/>
13+
public class PostgreSQLTestRun : TestRun
14+
{
15+
/// <summary>
16+
/// <para>
17+
/// The connection string.
18+
/// </para>
19+
/// <para></para>
20+
/// </summary>
21+
private readonly string _connectionString;
22+
23+
/// <summary>
24+
/// <para>
25+
/// Initializes a new <see cref="PostgreSQLTestRun"/> instance.
26+
/// </para>
27+
/// <para></para>
28+
/// </summary>
29+
/// <param name="connectionString">
30+
/// <para>A connection string.</para>
31+
/// <para></para>
32+
/// </param>
33+
public PostgreSQLTestRun(string connectionString) : base("postgresql")
34+
{
35+
_connectionString = connectionString;
36+
}
37+
38+
/// <summary>
39+
/// <para>
40+
/// Prepares this instance.
41+
/// </para>
42+
/// <para></para>
43+
/// </summary>
44+
public override void Prepare()
45+
{
46+
using var dbContext = new PostgreSQLDbContext(_connectionString);
47+
dbContext.Database.EnsureCreated();
48+
}
49+
50+
/// <summary>
51+
/// <para>
52+
/// Creates the list.
53+
/// </para>
54+
/// <para></para>
55+
/// </summary>
56+
public override void CreateList()
57+
{
58+
using var dbContext = new PostgreSQLDbContext(_connectionString);
59+
dbContext.BlogPosts.AddRange(BlogPosts.List);
60+
dbContext.SaveChanges();
61+
}
62+
63+
/// <summary>
64+
/// <para>
65+
/// Reads the list.
66+
/// </para>
67+
/// <para></para>
68+
/// </summary>
69+
public override void ReadList()
70+
{
71+
using var dbContext = new PostgreSQLDbContext(_connectionString);
72+
foreach (var blogPost in dbContext.BlogPosts)
73+
{
74+
ReadBlogPosts.Add(blogPost);
75+
}
76+
}
77+
78+
/// <summary>
79+
/// <para>
80+
/// Deletes the list.
81+
/// </para>
82+
/// <para></para>
83+
/// </summary>
84+
public override void DeleteList()
85+
{
86+
using var dbContext = new PostgreSQLDbContext(_connectionString);
87+
var blogPostsToDelete = dbContext.BlogPosts.ToList();
88+
dbContext.BlogPosts.RemoveRange(blogPostsToDelete);
89+
dbContext.SaveChanges();
90+
}
91+
}
92+
}

Program.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Collections.Generic;
44
using Comparisons.SQLiteVSDoublets.SQLite;
5+
using Comparisons.SQLiteVSDoublets.PostgreSQL;
56
using Comparisons.SQLiteVSDoublets.Doublets;
67
using Comparisons.SQLiteVSDoublets.Model;
78
using BenchmarkDotNet.Running;
@@ -28,19 +29,26 @@ private static void Run()
2829
const int numberOfRecordsPerTestRun = 1;
2930
BlogPosts.GenerateData(numberOfRecordsPerTestRun);
3031
var sqliteTestRuns = new List<SQLiteTestRun>();
32+
var postgresqlTestRuns = new List<PostgreSQLTestRun>();
3133
var doubletsTestRuns = new List<DoubletsTestRun>();
3234
for (int i = 0; i < numberOfTestRuns; i++)
3335
{
3436
var sqliteTestRun = new SQLiteTestRun("test.db");
3537
sqliteTestRun.Run();
3638
sqliteTestRuns.Add(sqliteTestRun);
39+
var postgresqlTestRun = new PostgreSQLTestRun("Host=localhost;Database=test;Username=test;Password=test");
40+
postgresqlTestRun.Run();
41+
postgresqlTestRuns.Add(postgresqlTestRun);
3742
var doubletsTestRun = new DoubletsTestRun("test.links");
3843
doubletsTestRun.Run();
3944
doubletsTestRuns.Add(doubletsTestRun);
4045
}
4146
Console.WriteLine("SQLite results:");
4247
var averageSqliteResults = GetResultsAverage(sqliteTestRuns);
4348
Console.WriteLine(averageSqliteResults.ToString());
49+
Console.WriteLine("PostgreSQL results:");
50+
var averagePostgreSqlResults = GetResultsAverage(postgresqlTestRuns);
51+
Console.WriteLine(averagePostgreSqlResults.ToString());
4452
Console.WriteLine("Doublets results:");
4553
var averageDoubletsResults = GetResultsAverage(doubletsTestRuns);
4654
Console.WriteLine(averageDoubletsResults.ToString());

0 commit comments

Comments
 (0)