Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
failed=0
for tfm in "${frameworks[@]}"; do
echo "::group::Testing $tfm"
if ! dotnet test src/ByteAether.Ulid.slnx --configuration CI-Debug -p:ImplTargetFramework=$tfm --verbosity normal --logger "trx;LogFileName=results-$tfm.trx"; then
if ! (cd src && dotnet test ByteAether.Ulid.slnx --configuration CI-Debug -p:ImplTargetFramework=$tfm --report-trx --report-trx-filename "results-$tfm.trx"); then
echo "❌ Tests failed for $tfm"
failed=1
fi
Expand Down
2 changes: 1 addition & 1 deletion src/Dapper.IntegrationTests/Dapper.IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.12" />
<PackageReference Include="Microsoft.Data.Sqlite" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/Dapper/Dapper.Impl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.4" />
<PackageReference Include="Dapper" VersionOverride="2.0.4" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Bcl.Memory" Version="10.0.10" />
<PackageReference Include="Microsoft.Bcl.Memory" />
</ItemGroup>

<ItemGroup>
Expand Down
7 changes: 4 additions & 3 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@
</ItemGroup>

<ItemGroup Condition="$(IsTestProject) == 'true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" />
<PackageReference Include="xunit.runner.visualstudio">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.v3" />

<Using Include="Xunit"/>
</ItemGroup>
Expand Down
19 changes: 19 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>

<ItemGroup>
<PackageVersion Include="Microsoft.Bcl.Memory" Version="10.0.10" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />

<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.9" />
<PackageVersion Include="linq2db" Version="6.3.0" />

<PackageVersion Include="xunit.v3" Version="4.0.0" />
<PackageVersion Include="Xunit.Combinatorial" Version="2.1.41" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="2.4.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
</ItemGroup>
</Project>
10 changes: 5 additions & 5 deletions src/EFCore.IntegrationTests/EFCore.IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.36" Condition="'$(TargetFramework)' == 'net6.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.20" Condition="'$(TargetFramework)' == 'net7.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.28" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.17" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9" Condition="'$(TargetFramework)' == 'net10.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" VersionOverride="6.0.36" Condition="'$(TargetFramework)' == 'net6.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" VersionOverride="7.0.20" Condition="'$(TargetFramework)' == 'net7.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" VersionOverride="8.0.28" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" VersionOverride="9.0.17" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" VersionOverride="10.0.9" Condition="'$(TargetFramework)' == 'net10.0'" />
</ItemGroup>

<ItemGroup>
Expand Down
50 changes: 25 additions & 25 deletions src/EFCore.IntegrationTests/UlidEntityFrameworkIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ public async Task EFCore_ShouldSuccessfullyRoundTrip_BothNonNullAndNullableUlids
await using (var writeContext = CreateContext(format))
{
writeContext.TestEntities.Add(entity);
await writeContext.SaveChangesAsync();
await writeContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}

// Act - Step 2: Read back from an isolated context instance & Query via Null comparison
await using (var readContext = CreateContext(format))
{
var dbEntity = await readContext.TestEntities.FirstOrDefaultAsync(e => e.SystemUlid == originalUlid);
var dbEntity = await readContext.TestEntities.FirstOrDefaultAsync(e => e.SystemUlid == originalUlid, cancellationToken: TestContext.Current.CancellationToken);

// Verify querying directly by matching a null column works flawlessly
var nullQueryEntity = await readContext.TestEntities.FirstOrDefaultAsync(e => e.NullableUlid == null);
var nullQueryEntity = await readContext.TestEntities.FirstOrDefaultAsync(e => e.NullableUlid == null, cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.NotNull(dbEntity);
Expand All @@ -72,27 +72,27 @@ public async Task EFCore_ShouldSuccessfullyRoundTrip_BothNonNullAndNullableUlids
var updatedUlid = Ulid.New();
dbEntity.NullableUlid = updatedUlid;
readContext.TestEntities.Update(dbEntity);
await readContext.SaveChangesAsync();
await readContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}

// Act - Step 4: Validate update retrieval
await using (var verifyContext = CreateContext(format))
{
var dbEntity = await verifyContext.TestEntities.FirstOrDefaultAsync();
var dbEntity = await verifyContext.TestEntities.FirstOrDefaultAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.NotNull(dbEntity);
Assert.Equal(originalUlid, dbEntity.SystemUlid);
Assert.NotNull(dbEntity.NullableUlid);

// Step 5: Test reversing a value back to null (Null-to-Null round trip)
dbEntity.NullableUlid = null;
verifyContext.TestEntities.Update(dbEntity);
await verifyContext.SaveChangesAsync();
await verifyContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}

// Act - Step 6: Final check that reverting to null persisted properly
await using (var finalVerifyContext = CreateContext(format))
{
var dbEntity = await finalVerifyContext.TestEntities.FirstOrDefaultAsync();
var dbEntity = await finalVerifyContext.TestEntities.FirstOrDefaultAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.NotNull(dbEntity);
Assert.Null(dbEntity.NullableUlid);
}
Expand All @@ -111,12 +111,12 @@ public async Task EFCore_ShouldTranslateLINQRangeQueries_ProperlyWithParameters(
var maxUlid = Ulid.MaxAt(DateTimeOffset.UtcNow.AddDays(1));

context.TestEntities.Add(new(){ SystemUlid = targetUlid });
await context.SaveChangesAsync();
await context.SaveChangesAsync(TestContext.Current.CancellationToken);

// Act - Evaluate if EF translation properly maps parameter types to database lookups
var results = await context.TestEntities
.Where(e => e.SystemUlid >= minUlid && e.SystemUlid <= maxUlid)
.ToListAsync();
.ToListAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Single(results);
Expand All @@ -135,18 +135,18 @@ public async Task EFCore_ShouldSuccessfullyProject_UlidToAnonymousAndDtoTypes(Ul
var targetUlid = Ulid.New();

context.TestEntities.Add(new() { SystemUlid = targetUlid, NullableUlid = Ulid.New() });
await context.SaveChangesAsync();
await context.SaveChangesAsync(TestContext.Current.CancellationToken);
context.ChangeTracker.Clear();

// Act - Step 1: Project into an anonymous type
var anonymousResult = await context.TestEntities
.Select(e => new { e.Id, e.SystemUlid, e.NullableUlid })
.FirstOrDefaultAsync(e => e.SystemUlid == targetUlid);
.FirstOrDefaultAsync(e => e.SystemUlid == targetUlid, cancellationToken: TestContext.Current.CancellationToken);

// Act - Step 2: Project directly into a raw primitive/value type collection
var rawUlidList = await context.TestEntities
.Select(e => e.SystemUlid)
.ToListAsync();
.ToListAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.NotNull(anonymousResult);
Expand All @@ -172,7 +172,7 @@ public async Task EFCore_ShouldTranslateContainsQuery_WhenUsingUlidCollections(U
new TestEntity { SystemUlid = Ulid.New(), NullableUlid = targetUlid },
new TestEntity { SystemUlid = Ulid.New(), NullableUlid = null }
);
await context.SaveChangesAsync();
await context.SaveChangesAsync(TestContext.Current.CancellationToken);
context.ChangeTracker.Clear();

// Strategy: Include null directly inside the searchable target criteria collection
Expand All @@ -181,7 +181,7 @@ public async Task EFCore_ShouldTranslateContainsQuery_WhenUsingUlidCollections(U
// Act
var results = await context.TestEntities
.Where(e => searchCriteria.Contains(e.NullableUlid))
.ToListAsync();
.ToListAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Equal(2, results.Count);
Expand Down Expand Up @@ -231,10 +231,10 @@ public async Task SchemaCreation_ShouldGenerateCorrectDatabaseColumnTypes(UlidSt
await using var command = _connection.CreateCommand();
command.CommandText = "PRAGMA table_info(TestEntities);";

await using var reader = await command.ExecuteReaderAsync();
await using var reader = await command.ExecuteReaderAsync(TestContext.Current.CancellationToken);

var foundSystemUlid = false;
while (await reader.ReadAsync())
while (await reader.ReadAsync(TestContext.Current.CancellationToken))
{
var columnName = reader.GetString(reader.GetOrdinal("name"));
if (columnName != nameof(TestEntity.SystemUlid))
Expand All @@ -261,9 +261,9 @@ public async Task EFCore_ShouldMaintainChronologicalOrder_WhenOrderingByUlid(Uli
await using var context = CreateContext(format);

var first = Ulid.New();
await Task.Delay(10); // Ensure timestamp progression if relying on machine clock
await Task.Delay(10, TestContext.Current.CancellationToken); // Ensure timestamp progression if relying on machine clock
var second = Ulid.New();
await Task.Delay(10);
await Task.Delay(10, TestContext.Current.CancellationToken);
var third = Ulid.New();

// Add them completely out of order
Expand All @@ -272,10 +272,10 @@ public async Task EFCore_ShouldMaintainChronologicalOrder_WhenOrderingByUlid(Uli
new TestEntity { SystemUlid = third },
new TestEntity { SystemUlid = first }
);
await context.SaveChangesAsync();
await context.SaveChangesAsync(TestContext.Current.CancellationToken);

// Act
var orderedList = await context.TestEntities.OrderBy(e => e.SystemUlid).ToListAsync();
var orderedList = await context.TestEntities.OrderBy(e => e.SystemUlid).ToListAsync(cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.Equal(3, orderedList.Count);
Expand Down Expand Up @@ -305,7 +305,7 @@ public async Task EFCore_ShouldSuccessfullyExecuteJoins_OnUlidProperties(UlidSto

context.TestEntities.Add(parentEntity);
context.Set<RelatedChildEntity>().Add(childEntity);
await context.SaveChangesAsync();
await context.SaveChangesAsync(TestContext.Current.CancellationToken);
context.ChangeTracker.Clear();

// Act - Explicit inner join execution over ULID properties
Expand All @@ -316,7 +316,7 @@ public async Task EFCore_ShouldSuccessfullyExecuteJoins_OnUlidProperties(UlidSto
child => child.ParentSystemUlid,
(parent, child) => new { parent.Id, parent.SystemUlid, child.Description }
)
.FirstOrDefaultAsync(x => x.SystemUlid == parentUlid);
.FirstOrDefaultAsync(x => x.SystemUlid == parentUlid, cancellationToken: TestContext.Current.CancellationToken);

// Assert
Assert.NotNull(joinResult);
Expand All @@ -336,18 +336,18 @@ public async Task EFCore_ShouldNotDetectFalseChanges_WhenEntityIsLoadedButUnmodi
await using (var setupContext = CreateContext(format))
{
setupContext.TestEntities.Add(new() { SystemUlid = originalUlid, NullableUlid = Ulid.New() });
await setupContext.SaveChangesAsync();
await setupContext.SaveChangesAsync(TestContext.Current.CancellationToken);
}

// Act & Assert
await using (var trackingContext = CreateContext(format))
{
// Load the entity completely into memory state tracking
var dbEntity = await trackingContext.TestEntities.FirstOrDefaultAsync(e => e.SystemUlid == originalUlid);
var dbEntity = await trackingContext.TestEntities.FirstOrDefaultAsync(e => e.SystemUlid == originalUlid, cancellationToken: TestContext.Current.CancellationToken);
Assert.NotNull(dbEntity);

// Attempt a Save without modifying any structural data properties
var affectedRows = await trackingContext.SaveChangesAsync();
var affectedRows = await trackingContext.SaveChangesAsync(TestContext.Current.CancellationToken);

// Verify that EF Core understands the model is completely clean
// (Returns 0 updates executed to the underlying data provider)
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore/EFCore.Impl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(TargetFramework.Replace('net', '')).0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore" VersionOverride="$(TargetFramework.Replace('net', '')).0.0">
<PrivateAssets>build;analyzers</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Bcl.Memory" Version="10.0.10" />
<PackageReference Include="Microsoft.Bcl.Memory" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="linq2db" Version="6.3.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.12" />
<PackageReference Include="linq2db" />
<PackageReference Include="Microsoft.Data.Sqlite" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading