Skip to content

Commit 2e408a0

Browse files
committed
Add commits order index
1 parent 8c46b45 commit 2e408a0

4 files changed

Lines changed: 74 additions & 63 deletions

File tree

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@
2626
<PackageVersion Include="linq2db" Version="6.2.1" />
2727
<PackageVersion Include="linq2db.EntityFrameworkCore" Version="10.3.0" />
2828
<PackageVersion Include="linq2db.Extensions" Version="6.2.1" />
29+
<PackageVersion Include="EFCore.ComplexIndexes" Version="2.0.2" />
2930
</ItemGroup>
3031
</Project>

src/SIL.Harmony.Tests/DbContextTests.VerifyModel.verified.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
Keys:
2525
Id PK
2626
Annotations:
27+
CustomIndex:CompositeIndexes: [{"paths":["HybridDateTime.DateTime","HybridDateTime.Counter","Id"],"unique":false,"name":"IX_Commits_DateTime_Counter_Id"}]
2728
Relational:FunctionName:
2829
Relational:Schema:
2930
Relational:SqlQuery:
Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,42 @@
1-
using System.Text.Json;
2-
using Microsoft.EntityFrameworkCore;
3-
using Microsoft.EntityFrameworkCore.Metadata.Builders;
4-
5-
namespace SIL.Harmony.Db.EntityConfig;
6-
7-
public class CommitEntityConfig : IEntityTypeConfiguration<Commit>
8-
{
9-
public void Configure(EntityTypeBuilder<Commit> builder)
10-
{
11-
builder.ToTable("Commits");
12-
builder.HasKey(c => c.Id);
13-
builder.ComplexProperty(c => c.HybridDateTime,
14-
hybridEntity =>
15-
{
16-
hybridEntity.Property(h => h.DateTime)
17-
.HasConversion(
18-
d => d.UtcDateTime,
19-
//need to use ticks here because the DateTime is stored as UTC, but the db records it as unspecified
20-
d => new DateTimeOffset(d.Ticks, TimeSpan.Zero))
21-
.HasColumnName("DateTime");
22-
hybridEntity.Property(h => h.Counter).HasColumnName("Counter");
23-
});
24-
builder.Property(c => c.Metadata)
25-
.HasColumnType("jsonb")
26-
.HasConversion(
27-
m => JsonSerializer.Serialize(m, (JsonSerializerOptions?)null),
28-
json => JsonSerializer.Deserialize<CommitMetadata>(json, (JsonSerializerOptions?)null) ?? new()
29-
);
30-
builder.HasMany(c => c.ChangeEntities)
31-
.WithOne()
32-
.HasForeignKey(c => c.CommitId);
33-
}
34-
}
1+
using System.Text.Json;
2+
using EFCore.ComplexIndexes;
3+
using Microsoft.EntityFrameworkCore;
4+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
5+
6+
namespace SIL.Harmony.Db.EntityConfig;
7+
8+
public class CommitEntityConfig : IEntityTypeConfiguration<Commit>
9+
{
10+
public void Configure(EntityTypeBuilder<Commit> builder)
11+
{
12+
builder.ToTable("Commits");
13+
builder.HasKey(c => c.Id);
14+
builder.ComplexProperty(c => c.HybridDateTime,
15+
hybridEntity =>
16+
{
17+
hybridEntity.Property(h => h.DateTime)
18+
.HasConversion(
19+
d => d.UtcDateTime,
20+
//need to use ticks here because the DateTime is stored as UTC, but the db records it as unspecified
21+
d => new DateTimeOffset(d.Ticks, TimeSpan.Zero))
22+
.HasColumnName("DateTime");
23+
hybridEntity.Property(h => h.Counter).HasColumnName("Counter");
24+
});
25+
// Supports Harmony's default ordering (DateTime DESC, Counter DESC, Id DESC).
26+
// EF Core 10 cannot express indexes mixing ComplexProperty members + scalars (efcore#11336, targeted for 11).
27+
// We use EFCore.ComplexIndexes instead. The package doesn't support column direction,
28+
// but an ASC index apparently works equivalently for reverse scans on SQLite, Postgres, and SQL Server.
29+
builder.HasComplexCompositeIndex(
30+
c => new { c.HybridDateTime.DateTime, c.HybridDateTime.Counter, c.Id },
31+
indexName: "IX_Commits_DateTime_Counter_Id");
32+
builder.Property(c => c.Metadata)
33+
.HasColumnType("jsonb")
34+
.HasConversion(
35+
m => JsonSerializer.Serialize(m, (JsonSerializerOptions?)null),
36+
json => JsonSerializer.Deserialize<CommitMetadata>(json, (JsonSerializerOptions?)null) ?? new()
37+
);
38+
builder.HasMany(c => c.ChangeEntities)
39+
.WithOne()
40+
.HasForeignKey(c => c.CommitId);
41+
}
42+
}

src/SIL.Harmony/SIL.Harmony.csproj

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
3-
<PropertyGroup>
4-
<RootNamespace>SIL.Harmony</RootNamespace>
5-
<IsPackable>true</IsPackable>
6-
</PropertyGroup>
7-
8-
<ItemGroup>
9-
<InternalsVisibleTo Include="SIL.Harmony.Tests" />
10-
</ItemGroup>
11-
12-
<ItemGroup>
13-
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
14-
<PrivateAssets>all</PrivateAssets>
15-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16-
</PackageReference>
17-
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
18-
<PackageReference Include="Nito.AsyncEx.Coordination" />
19-
</ItemGroup>
20-
21-
<ItemGroup>
22-
<ProjectReference Include="..\SIL.Harmony.Core\SIL.Harmony.Core.csproj" />
23-
</ItemGroup>
24-
25-
<ItemGroup>
26-
<Using Include="SIL.Harmony.Core"/>
27-
</ItemGroup>
28-
29-
</Project>
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<RootNamespace>SIL.Harmony</RootNamespace>
5+
<IsPackable>true</IsPackable>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<InternalsVisibleTo Include="SIL.Harmony.Tests" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
18+
<PackageReference Include="EFCore.ComplexIndexes" />
19+
<PackageReference Include="Nito.AsyncEx.Coordination" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\SIL.Harmony.Core\SIL.Harmony.Core.csproj" />
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<Using Include="SIL.Harmony.Core"/>
28+
</ItemGroup>
29+
30+
</Project>

0 commit comments

Comments
 (0)