Skip to content

Commit 94851a3

Browse files
committed
Add DbPool life test
1 parent 0d158db commit 94851a3

File tree

9 files changed

+158
-82
lines changed

9 files changed

+158
-82
lines changed

src/plugins/EfCore/EfCorePoolTest/BlogTest.cs

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using EfCoreTest;
22
using Microsoft.EntityFrameworkCore;
33
using Microsoft.Extensions.DependencyInjection;
4+
using System.Runtime.InteropServices;
45

56
namespace EfCorePoolTest;
67

7-
internal sealed class BlogTest
8+
public sealed class BlogTest
89
{
910
public BlogTest()
1011
{
@@ -19,57 +20,98 @@ public BlogTest()
1920

2021
#region Methods
2122

22-
private async Task AddWithFactory()
23+
private async Task AddByScopeAsync(long id, CancellationToken cancellationToken)
2324
{
24-
await using var dbContext = await ServiceProvider.GetRequiredService<IDbContextFactory<TestDbContext>>()
25-
.CreateDbContextAsync();
25+
using var scope = ServiceProvider.CreateScope();
26+
await using var dbContext = scope.ServiceProvider.GetRequiredService<TestDbContext>();
27+
Console.WriteLine(dbContext.Id);
28+
29+
_ = await dbContext.Blogs.AddAsync(new Blog(id, "add1", "test"), cancellationToken);
2630

27-
await dbContext.Blogs.AddAsync(new Blog(1003, "add3", "test"));
31+
await Task.Delay(100, cancellationToken);
2832

29-
await dbContext.SaveChangesAsync();
33+
_ = await dbContext.SaveChangesAsync(cancellationToken);
3034
}
3135

32-
public async Task Add_Test()
36+
private async Task AddWithFactoryAsync(CancellationToken cancellationToken = default)
3337
{
34-
using var scope = ServiceProvider.CreateScope();
35-
await using var dbContext = scope.ServiceProvider.GetRequiredService<TestDbContext>();
38+
await using var dbContext = await ServiceProvider.GetRequiredService<IDbContextFactory<TestDbContext>>()
39+
.CreateDbContextAsync(cancellationToken);
3640

37-
await dbContext.Blogs.AddAsync(new Blog(1001, "add1", "test"));
38-
await dbContext.Blogs.AddAsync(new Blog(1002, "add2", "test"));
41+
_ = await dbContext.Blogs.AddAsync(new Blog(1003, "add3", "test"), cancellationToken);
3942

40-
await dbContext.SaveChangesAsync();
43+
_ = await dbContext.SaveChangesAsync(cancellationToken);
4144
}
4245

43-
public async Task Add_Thrice_Test()
46+
public async Task Add_TestAsync(CancellationToken cancellationToken = default)
4447
{
45-
var t1 = Add_Test();
46-
var t2 = Add_Test();
48+
await AddByScopeAsync(1001, cancellationToken);
49+
}
4750

48-
await Task.Delay(1_000);
51+
public async Task Add_Thrice_TestAsync(CancellationToken cancellationToken = default)
52+
{
53+
// pool size 2
54+
var t1 = AddByScopeAsync(2001, cancellationToken);
55+
var t2 = AddByScopeAsync(2002, cancellationToken);
56+
var t3 = AddByScopeAsync(2003, cancellationToken);
4957

50-
var t3 = Add_Test();
58+
await Task.Delay(1_000, cancellationToken);
5159

52-
await Task.WhenAll(t1, t2, t3);
60+
var t4 = AddByScopeAsync(2004, cancellationToken);
61+
var t5 = AddByScopeAsync(2005, cancellationToken);
62+
63+
await Task.WhenAll(t1, t2, t3, t4);
5364
}
5465

55-
public async Task IDbContextFactory_Test()
66+
public async Task IDbContextFactory_TestAsync(CancellationToken cancellationToken = default)
5667
{
57-
var t1 = AddWithFactory();
58-
var t2 = AddWithFactory();
68+
var t1 = AddWithFactoryAsync(cancellationToken);
69+
var t2 = AddWithFactoryAsync(cancellationToken);
5970

60-
await Task.Delay(1_000);
71+
await Task.Delay(1_000, default);
6172

62-
var t3 = AddWithFactory();
73+
var t3 = AddWithFactoryAsync(cancellationToken);
6374

6475
await Task.WhenAll(t1, t2, t3);
6576
}
6677

67-
public async Task Select_Test()
78+
public unsafe void ScopeInstance_Test()
79+
{
80+
using var scope = ServiceProvider.CreateScope();
81+
var dbContext1 = scope.ServiceProvider.GetRequiredService<TestDbContext>();
82+
var dbContext2 = scope.ServiceProvider.GetRequiredService<TestDbContext>();
83+
84+
var handle1 = GCHandle.Alloc(dbContext1, GCHandleType.Normal);
85+
var handle2 = GCHandle.Alloc(dbContext2, GCHandleType.Normal);
86+
var ptr1 = GCHandle.ToIntPtr(handle1);
87+
var ptr2 = GCHandle.ToIntPtr(handle2);
88+
89+
// the variables location
90+
Console.WriteLine(ptr1);
91+
Console.WriteLine(ptr2);
92+
93+
handle2.Free();
94+
handle1.Free();
95+
96+
// the instance location in heap
97+
fixed (long* p = &dbContext1.Id)
98+
{
99+
Console.WriteLine(*p);
100+
}
101+
fixed (long* p = &dbContext2.Id)
102+
{
103+
Console.WriteLine(*p);
104+
}
105+
106+
Console.WriteLine(ReferenceEquals(dbContext1, dbContext2));
107+
}
108+
109+
public async Task Select_TestAsync(CancellationToken cancellationToken = default)
68110
{
69111
using var scope = ServiceProvider.CreateScope();
70112
await using var dbContext = scope.ServiceProvider.GetRequiredService<TestDbContext>();
71113

72-
var list = await dbContext.Blogs.ToListAsync();
114+
var list = await dbContext.Blogs.ToListAsync(cancellationToken: cancellationToken);
73115
}
74116

75117
#endregion

src/plugins/EfCore/EfCorePoolTest/DependencyInjection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal static class DependencyInjection
77

88
#region Constants & Statics
99

10-
public static ServiceProvider ServiceProvider { get; set; } = null!;
10+
internal static ServiceProvider ServiceProvider { get; set; } = null!;
1111

1212
#endregion
1313

src/plugins/EfCore/EfCorePoolTest/EfCorePoolTest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<TargetFramework>net9.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8+
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
89
</PropertyGroup>
910

1011
<ItemGroup>
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,44 @@
1-
using EfCorePoolTest;
21
using EfCoreTest;
32
using Microsoft.EntityFrameworkCore;
43
using Microsoft.Extensions.DependencyInjection;
54

6-
var services = new ServiceCollection();
5+
namespace EfCorePoolTest;
76

8-
services.AddDbContextPool<TestDbContext>(SettingBuilder, 2);
9-
services.AddPooledDbContextFactory<TestDbContext>(SettingBuilder, 2);
7+
internal static class Program
8+
{
109

11-
DependencyInjection.ServiceProvider = services.BuildServiceProvider();
10+
#region Constants & Statics
1211

13-
var blogTest = new BlogTest();
12+
private static void Main()
13+
{
14+
var services = new ServiceCollection();
1415

15-
//await blogTest.Add_Test();
16+
_ = services.AddDbContextPool<TestDbContext>(SettingBuilder, 2);
17+
_ = services.AddPooledDbContextFactory<TestDbContext>(SettingBuilder, 2);
1618

17-
await blogTest.Add_Thrice_Test();
19+
DependencyInjection.ServiceProvider = services.BuildServiceProvider();
1820

19-
await blogTest.Select_Test();
21+
var blogTest = new BlogTest();
2022

21-
await blogTest.IDbContextFactory_Test();
23+
//await blogTest.Add_TestAsync(default);
2224

23-
return;
25+
//await blogTest.Add_Thrice_TestAsync(default);
26+
27+
blogTest.ScopeInstance_Test();
28+
29+
//await blogTest.Select_TestAsync(default);
30+
31+
//await blogTest.IDbContextFactory_TestAsync(default);
32+
33+
return;
34+
35+
static void SettingBuilder(DbContextOptionsBuilder builder)
36+
{
37+
DbContextTest.SettingBuilder(builder);
38+
DbContextTest.UseSqlServer(builder);
39+
}
40+
}
41+
42+
#endregion
2443

25-
static void SettingBuilder(DbContextOptionsBuilder builder)
26-
{
27-
DbContextTest.SettingBuilder(builder);
28-
DbContextTest.UseSqlServer(builder);
2944
}
Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
11
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Metadata.Builders;
33

4-
namespace EfCoreTest
4+
namespace EfCoreTest;
5+
6+
public class BlogMapping : IEntityTypeConfiguration<Blog>
57
{
6-
public class BlogMapping : IEntityTypeConfiguration<Blog>
8+
9+
#region IEntityTypeConfiguration implementations
10+
11+
/// <inheritdoc/>
12+
public void Configure(EntityTypeBuilder<Blog> builder)
713
{
8-
/// <inheritdoc />
9-
public void Configure(EntityTypeBuilder<Blog> builder)
10-
{
11-
builder.HasKey(o => o.Id);
12-
//*..1
13-
builder.HasMany(p => p.BlogTags).WithOne().HasForeignKey(o => o.BlogId).OnDelete(DeleteBehavior.Cascade);
14-
}
14+
builder.HasKey(o => o.Id);
15+
//*..1
16+
builder.HasMany(p => p.BlogTags).WithOne().HasForeignKey(o => o.BlogId).OnDelete(DeleteBehavior.Cascade);
1517
}
1618

17-
public class BlogTaggMapping : IEntityTypeConfiguration<BlogTag>
19+
#endregion
20+
21+
}
22+
23+
public class BlogTagMapping : IEntityTypeConfiguration<BlogTag>
24+
{
25+
26+
#region IEntityTypeConfiguration implementations
27+
28+
/// <inheritdoc/>
29+
public void Configure(EntityTypeBuilder<BlogTag> builder)
1830
{
19-
/// <inheritdoc />
20-
public void Configure(EntityTypeBuilder<BlogTag> builder)
21-
{
22-
builder.HasKey(o => o.Id);
23-
}
31+
builder.HasKey(o => o.Id);
2432
}
33+
34+
#endregion
35+
2536
}

src/plugins/EfCore/EfCoreTest/Shared/DbContextTest.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ public abstract class DbContextTest
99
{
1010

1111
#region Constants & Statics
12-
public static SqliteConnection? SqliteConnection;
1312

14-
protected static void AddIfNotExists<T>(TestDbContext dbContext, T entity) where T : Entity
13+
public static SqliteConnection? SqliteConnection { get; private set; }
14+
15+
protected static void AddIfNotExists<T>(TestDbContext dbContext, T entity)
16+
where T : Entity
1517
{
1618
var dbSet = dbContext.Set<T>();
1719
if (!dbSet.Any(arg => EF.Property<long>(arg, "Id") == entity.Id))
1820
{
19-
dbSet.Add(entity);
21+
_ = dbSet.Add(entity);
2022
}
2123
}
2224

@@ -58,7 +60,7 @@ protected static TestDbContext CreateSqliteMemoryDbContext()
5860
}
5961

6062
var builder = CreateBuilder();
61-
builder.UseSqlite(SqliteConnection);
63+
_ = builder.UseSqlite(SqliteConnection);
6264

6365
if (SqliteConnection.State != ConnectionState.Open)
6466
{
@@ -68,29 +70,31 @@ protected static TestDbContext CreateSqliteMemoryDbContext()
6870

6971
if (createDb)
7072
{
71-
dbContext.Database.EnsureCreated();
73+
_ = dbContext.Database.EnsureCreated();
7274
}
7375

7476
return dbContext;
7577
}
7678

7779
public static void SettingBuilder(DbContextOptionsBuilder builder)
7880
{
79-
builder.LogTo(Console.WriteLine, LogLevel.Information);
80-
builder.EnableSensitiveDataLogging();
81-
builder.EnableDetailedErrors();
81+
_ = builder.LogTo(Console.WriteLine, LogLevel.Information);
82+
_ = builder.EnableSensitiveDataLogging();
83+
_ = builder.EnableDetailedErrors();
8284
}
8385

8486
public static void UseNpgsql(DbContextOptionsBuilder builder)
8587
{
86-
builder.UseNpgsql(@"Host=localhost;Port=5432;Database=EfCoreTest;Username=postgres;Password=123456;");
88+
_ = builder.UseNpgsql(@"Host=localhost;Port=5432;Database=EfCoreTest;Username=postgres;Password=123456;");
8789
}
8890

8991
public static void UseSqlServer(DbContextOptionsBuilder builder)
9092
{
91-
builder.UseSqlServer(@"Server=.\sql2017;Initial Catalog=EfCoreTest;User ID=sa;Password=123456");
93+
_ = builder.UseSqlServer(
94+
@"Server=.\sql2017;Initial Catalog=EfCoreTest;User ID=sa;Password=123456;TrustServerCertificate=true");
9295
//builder.UseSqlServer(@"Server=localhost;Initial Catalog=EfCoreTest;User ID=sa;Password=qwer@1234");
9396
}
97+
9498
#endregion
9599

96100
}

src/plugins/EfCore/EfCoreTest/Shared/TestDbContext.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using EfCoreTest.Paging;
22
using Microsoft.EntityFrameworkCore;
3+
using System.Diagnostics;
34
using System.Reflection;
45

56
namespace EfCoreTest;
@@ -19,14 +20,14 @@ private static void CreateSeed(ModelBuilder modelBuilder)
1920
var teacher = new Teacher(2, "teacher");
2021
_ = modelBuilder.Entity<Teacher>().HasData(teacher);
2122

22-
var person = new Person(1, "name", family.Id, null);
23+
var person = new Person(1, "name", family.Id);
2324
var person2 = new Person(2, "name", family2.Id, teacher.Id);
2425
var person3 = new Person(3, "name", family3.Id, teacher.Id);
2526
_ = modelBuilder.Entity<Person>().HasData(person, person2, person3);
2627

2728
for (var i = 0; i < 100; i++)
2829
{
29-
_ = modelBuilder.Entity<Person>().HasData(new Person(100 + i, $"name{i}", family2.Id, null));
30+
_ = modelBuilder.Entity<Person>().HasData(new Person(100 + i, $"name{i}", family2.Id));
3031
}
3132

3233
//todo: Data Seeding not support navigations https://github.com/dotnet/efcore/issues/25586
@@ -60,6 +61,7 @@ private static void CreateSeed(ModelBuilder modelBuilder)
6061

6162
public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
6263
{
64+
Id = Stopwatch.GetTimestamp();
6365
}
6466

6567
#region Properties
@@ -125,6 +127,12 @@ public int SaveChanges(bool softDelete, bool acceptAllChangesOnSuccess = true)
125127

126128
#endregion
127129

130+
#region Self props
131+
132+
public long Id;
133+
134+
#endregion
135+
128136
#region DatabaseProvider
129137

130138
public enum EfCoreDatabaseProvider
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//SonarQube Extension save in C:\Users\x\AppData\Roaming\SonarLint for Visual Studio
2+
{
3+
"sonarlint.rules": {
4+
},
5+
"sonarlint.analyzerProperties": {
6+
"sonar.cs.analyzeGeneratedCode": "false"
7+
},
8+
"sonarlint.analysisExcludesStandalone": "**/_Generated/**,**/Migrations/**"
9+
}

0 commit comments

Comments
 (0)