Skip to content

Commit c06aee2

Browse files
CopilotPhenX
andcommitted
Update benchmark to generate entities with children when UseIncludeGraph is true
Co-authored-by: PhenX <42170+PhenX@users.noreply.github.com>
1 parent f811609 commit c06aee2

3 files changed

Lines changed: 70 additions & 9 deletions

File tree

tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark/LibComparator.cs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public abstract partial class LibComparator
2121

2222
/// <summary>
2323
/// Set to true to benchmark with IncludeGraph option enabled.
24-
/// Default is false, which runs the benchmark exactly as before.
24+
/// When true, each entity will have 2 child entities for graph insertion benchmarking.
25+
/// Default is false, which runs the benchmark exactly as before (flat entities only).
2526
/// </summary>
2627
public bool UseIncludeGraph { get; set; } = false;
2728

@@ -31,12 +32,27 @@ public abstract partial class LibComparator
3132
[IterationSetup]
3233
public void IterationSetup()
3334
{
34-
data = Enumerable.Range(1, N).Select(i => new TestEntity
35+
data = Enumerable.Range(1, N).Select(i =>
3536
{
36-
Name = $"Entity{i}",
37-
Price = (decimal)(i * 0.1),
38-
Identifier = Guid.NewGuid(),
39-
NumericEnumValue = (NumericEnum)(i % 2),
37+
var entity = new TestEntity
38+
{
39+
Name = $"Entity{i}",
40+
Price = (decimal)(i * 0.1),
41+
Identifier = Guid.NewGuid(),
42+
NumericEnumValue = (NumericEnum)(i % 2),
43+
};
44+
45+
// When UseIncludeGraph is true, add child entities for graph insertion benchmarking
46+
if (UseIncludeGraph)
47+
{
48+
entity.Children = new List<TestEntityChild>
49+
{
50+
new TestEntityChild { Description = $"Child1 of Entity{i}", Quantity = i },
51+
new TestEntityChild { Description = $"Child2 of Entity{i}", Quantity = i * 2 },
52+
};
53+
}
54+
55+
return entity;
4056
}).ToList();
4157

4258
ConfigureDbContext();
@@ -79,6 +95,12 @@ await DbContext.ExecuteBulkInsertAsync(data, options =>
7995
[Benchmark]
8096
public void RawInsert()
8197
{
98+
if (UseIncludeGraph)
99+
{
100+
// Raw insert doesn't support graph insertion - skip when UseIncludeGraph is true
101+
return;
102+
}
103+
82104
if (DbContext.Database.ProviderName!.Contains("SqlServer", StringComparison.InvariantCultureIgnoreCase))
83105
{
84106
// Use SqlBulkCopy for SQL Server
@@ -109,6 +131,12 @@ public void RawInsert()
109131
[Benchmark]
110132
public async Task Linq2Db()
111133
{
134+
if (UseIncludeGraph)
135+
{
136+
// Linq2Db doesn't support graph insertion - skip when UseIncludeGraph is true
137+
return;
138+
}
139+
112140
await DbContext.BulkCopyAsync(new BulkCopyOptions
113141
{
114142
BulkCopyType = BulkCopyType.ProviderSpecific,
@@ -118,7 +146,7 @@ await DbContext.BulkCopyAsync(new BulkCopyOptions
118146
[Benchmark]
119147
public async Task Z_EntityFramework_Extensions_EFCore()
120148
{
121-
await DbContext.BulkInsertOptimizedAsync(data, options => options.IncludeGraph = false);
149+
await DbContext.BulkInsertOptimizedAsync(data, options => options.IncludeGraph = UseIncludeGraph);
122150
}
123151

124152
// [Benchmark]
@@ -132,8 +160,8 @@ public async Task EFCore_BulkExtensions()
132160
{
133161
await DbContext.BulkInsertAsync(data, options =>
134162
{
135-
options.IncludeGraph = false;
136-
options.PreserveInsertOrder = false;
163+
options.IncludeGraph = UseIncludeGraph;
164+
options.PreserveInsertOrder = UseIncludeGraph; // Required for graph insertion
137165
});
138166
}
139167

tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark/TestDbContext.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,22 @@ public class TestDbContext(Action<DbContextOptionsBuilder> configure) : DbContex
77
public Action<DbContextOptionsBuilder> Configure { get; } = configure;
88

99
public DbSet<TestEntity> TestEntities { get; set; } = null!;
10+
public DbSet<TestEntityChild> TestEntityChildren { get; set; } = null!;
1011

1112
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
1213
{
1314
Configure(optionsBuilder);
1415
}
16+
17+
protected override void OnModelCreating(ModelBuilder modelBuilder)
18+
{
19+
base.OnModelCreating(modelBuilder);
20+
21+
modelBuilder.Entity<TestEntity>(builder =>
22+
{
23+
builder.HasMany(e => e.Children)
24+
.WithOne(c => c.TestEntity)
25+
.HasForeignKey(c => c.TestEntityId);
26+
});
27+
}
1528
}

tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark/TestEntity.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ public class TestEntity
1717
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
1818

1919
public NumericEnum NumericEnumValue { get; set; }
20+
21+
/// <summary>
22+
/// Child entities for IncludeGraph benchmarking.
23+
/// </summary>
24+
public ICollection<TestEntityChild> Children { get; set; } = new List<TestEntityChild>();
25+
}
26+
27+
/// <summary>
28+
/// Child entity for benchmarking IncludeGraph with navigation properties.
29+
/// </summary>
30+
[PrimaryKey(nameof(Id))]
31+
[Table(nameof(TestEntityChild))]
32+
public class TestEntityChild
33+
{
34+
public int Id { get; set; }
35+
public string Description { get; set; } = string.Empty;
36+
public int Quantity { get; set; }
37+
38+
public int TestEntityId { get; set; }
39+
public TestEntity TestEntity { get; set; } = null!;
2040
}
2141

2242
public enum NumericEnum

0 commit comments

Comments
 (0)