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
6 changes: 3 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project>
<PropertyGroup>
<EFCoreVersion>11.0.0-preview.4.26210.110</EFCoreVersion>
<MicrosoftExtensionsVersion>11.0.0-preview.4.26210.110</MicrosoftExtensionsVersion>
<MicrosoftExtensionsConfigurationVersion>11.0.0-preview.4.26210.110</MicrosoftExtensionsConfigurationVersion>
<EFCoreVersion>11.0.0-preview.4.26215.121</EFCoreVersion>
<MicrosoftExtensionsVersion>11.0.0-preview.4.26215.121</MicrosoftExtensionsVersion>
<MicrosoftExtensionsConfigurationVersion>11.0.0-preview.4.26215.121</MicrosoftExtensionsConfigurationVersion>
<NpgsqlVersion>10.0.0</NpgsqlVersion>
</PropertyGroup>

Expand Down
28 changes: 2 additions & 26 deletions src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal;
/// </summary>
public class NpgsqlHistoryRepository : HistoryRepository, IHistoryRepository
{
private IModel? _model;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down Expand Up @@ -111,7 +109,9 @@ protected override IReadOnlyList<MigrationCommand> GetCreateCommands()
// Note that the approach in EF is to remove specific conventions (e.g. DbSetFindingConvention), but we don't want to hardcode
// specific conventions here; for example, the NetTopologySuite plugin has its NpgsqlNetTopologySuiteExtensionAddingConvention
// which adds PostGIS. So we just filter out the annotations on the operations themselves.
#pragma warning disable EF1001 // Internal EF Core API usage.
var model = EnsureModel();
#pragma warning restore EF1001 // Internal EF Core API usage.

var operations = Dependencies.ModelDiffer.GetDifferences(null, model.GetRelationalModel());

Expand All @@ -135,30 +135,6 @@ protected override IReadOnlyList<MigrationCommand> GetCreateCommands()
return Dependencies.MigrationsSqlGenerator.Generate(operations, model);
}

// Copied as-is from EF's HistoryRepository, since it's private (see https://github.com/dotnet/efcore/issues/34991)
private IModel EnsureModel()
{
if (_model == null)
{
var conventionSet = Dependencies.ConventionSetBuilder.CreateConventionSet();

conventionSet.Remove(typeof(DbSetFindingConvention));
conventionSet.Remove(typeof(RelationalDbFunctionAttributeConvention));

var modelBuilder = new ModelBuilder(conventionSet);
modelBuilder.Entity<HistoryRow>(x =>
{
ConfigureTable(x);
x.ToTable(TableName, TableSchema);
});

_model = Dependencies.ModelRuntimeInitializer.Initialize(
(IModel)modelBuilder.Model, designTime: true, validationLogger: null);
}

return _model;
}

bool IHistoryRepository.CreateIfNotExists()
{
// In PG, doing CREATE TABLE IF NOT EXISTS isn't concurrency-safe, and can result a "duplicate table" error or in a unique
Expand Down
6 changes: 3 additions & 3 deletions test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,14 @@ public override Task Can_read_write_nullable_TimeSpan_JSON_values(string? value,
// Cannot override since the base test contains [InlineData] attributes which still apply, and which contain data we need
// to override. See Can_read_write_nullable_TimeSpan_JSON_values_npgsql instead.
// TODO: Implement Can_read_write_collection_of_TimeSpan_JSON_values_npgsql
public override Task Can_read_write_collection_of_TimeSpan_JSON_values()
public override Task Can_read_write_collection_of_TimeSpan_JSON_values(string expected)
=> Task.CompletedTask;
Comment on lines 155 to 159
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says to see Can_read_write_nullable_TimeSpan_JSON_values_npgsql instead, but no such method exists in this class (and the TODO indicates it’s not implemented yet). This cross-reference is misleading—either implement the referenced *_npgsql test method or update the comment to point at the correct helper/placeholder for the TimeSpan collection case.

Copilot uses AI. Check for mistakes.

// Cannot override since the base test contains [InlineData] attributes which still apply, and which contain data we need
// to override. See Can_read_write_nullable_TimeSpan_JSON_values_npgsql instead.
// TODO: Implement Can_read_write_collection_of_nullable_TimeSpan_JSON_values_npgsql
public override Task Can_read_write_collection_of_nullable_TimeSpan_JSON_values()
=> Task.CompletedTask;
public override Task Can_read_write_collection_of_nullable_TimeSpan_JSON_values(string expected)
=> Task.CompletedTask;
Comment on lines 161 to +165
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment points to Can_read_write_nullable_TimeSpan_JSON_values_npgsql, but that method isn’t implemented anywhere in this file. Consider updating the comment to reference the intended Can_read_write_collection_of_nullable_TimeSpan_JSON_values_npgsql (if that’s the plan) or adding the missing *_npgsql method so readers know where the provider-specific coverage lives.

Copilot uses AI. Check for mistakes.

#endregion TimeSpan

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2355,6 +2355,63 @@ public override async Task Project_inline_collection_with_Concat()
AssertSql();
}

public override async Task Parameter_collection_of_enum_Cast_from_different_enum_type(ParameterTranslationMode mode)
{
await base.Parameter_collection_of_enum_Cast_from_different_enum_type(mode);

switch (mode)
{
case ParameterTranslationMode.Constant:
{
AssertSql(
"""
SELECT t."Id"
FROM "TestEntity38008" AS t
WHERE EXISTS (
SELECT 1
FROM (VALUES (2::int)) AS f("Value")
WHERE f."Value" = t."Status")
""");
break;
}

case ParameterTranslationMode.Parameter:
{
AssertSql(
"""
@filter={ '2' } (DbType = Object)

SELECT t."Id"
FROM "TestEntity38008" AS t
WHERE EXISTS (
SELECT 1
FROM unnest(@filter) AS f(value)
WHERE f.value = t."Status")
""");
break;
}

case ParameterTranslationMode.MultipleParameters:
{
AssertSql(
"""
@filter1='2'

SELECT t."Id"
FROM "TestEntity38008" AS t
WHERE EXISTS (
SELECT 1
FROM (VALUES (@filter1)) AS f("Value")
WHERE f."Value" = t."Status")
""");
break;
}

default:
throw new NotImplementedException();
}
}

public override async Task Nested_contains_with_Lists_and_no_inferred_type_mapping()
{
await base.Nested_contains_with_Lists_and_no_inferred_type_mapping();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,34 @@ SELECT CAST(b."DateTimeOffset" AT TIME ZONE 'UTC' AS time)
""");
}

public override async Task DateTime()
{
await base.DateTime();

AssertSql(
"""
SELECT b."Id", b."Bool", b."Byte", b."ByteArray", b."DateOnly", b."DateTime", b."DateTimeOffset", b."Decimal", b."Double", b."Enum", b."FlagsEnum", b."Float", b."Guid", b."Int", b."Long", b."Short", b."String", b."TimeOnly", b."TimeSpan"
FROM "BasicTypesEntities" AS b
WHERE b."DateTimeOffset" AT TIME ZONE 'UTC' = TIMESTAMP '1998-05-04T15:30:10'
""");
}

// The base test compares DateTimeOffset.UtcDateTime with an Unspecified DateTime, which Npgsql can't generate as a timestamptz literal
public override Task UtcDateTime()
=> Assert.ThrowsAsync<ArgumentException>(() => base.UtcDateTime());

public override async Task LocalDateTime()
{
await base.LocalDateTime();

AssertSql(
"""
SELECT b."Id", b."Bool", b."Byte", b."ByteArray", b."DateOnly", b."DateTime", b."DateTimeOffset", b."Decimal", b."Double", b."Enum", b."FlagsEnum", b."Float", b."Guid", b."Int", b."Long", b."Short", b."String", b."TimeOnly", b."TimeSpan"
FROM "BasicTypesEntities" AS b
WHERE b."DateTimeOffset"::timestamp > TIMESTAMP '1999-01-01T00:00:00'
""");
}

public override async Task AddYears()
{
await base.AddYears();
Expand Down Expand Up @@ -222,6 +250,15 @@ public override Task ToUnixTimeMilliseconds()
public override Task ToUnixTimeSecond()
=> AssertTranslationFailed(() => base.ToUnixTimeSecond());

public override Task ToOffset()
=> AssertTranslationFailed(() => base.ToOffset());

public override Task Ctor_DateTime()
=> AssertTranslationFailed(() => base.Ctor_DateTime());

public override Task Ctor_DateTime_TimeSpan()
=> AssertTranslationFailed(() => base.Ctor_DateTime_TimeSpan());

public override async Task Milliseconds_parameter_and_constant()
{
await base.Milliseconds_parameter_and_constant();
Expand Down
Loading