Skip to content

Commit

Permalink
Sync to EF Core 9.0.0-preview.7.24405.3 (#3258)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Sep 1, 2024
1 parent 36295e9 commit f3fb1a6
Show file tree
Hide file tree
Showing 136 changed files with 3,005 additions and 1,724 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<VersionPrefix>9.0.0-preview.4</VersionPrefix>
<VersionPrefix>9.0.0-preview.7</VersionPrefix>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AnalysisLevel>latest</AnalysisLevel>
Expand Down
17 changes: 9 additions & 8 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<EFCoreVersion>9.0.0-preview.3.24172.4</EFCoreVersion>
<MicrosoftExtensionsVersion>9.0.0-preview.3.24172.9</MicrosoftExtensionsVersion>
<EFCoreVersion>[9.0.0-preview.7.24405.3]</EFCoreVersion>
<MicrosoftExtensionsVersion>9.0.0-preview.7.24405.7</MicrosoftExtensionsVersion>
<NpgsqlVersion>8.0.3</NpgsqlVersion>
</PropertyGroup>

Expand All @@ -21,14 +21,15 @@
<PackageVersion Include="Npgsql.NetTopologySuite" Version="$(NpgsqlVersion)" />
<PackageVersion Include="Npgsql.DependencyInjection" Version="$(NpgsqlVersion)" />

<!-- Workaround for unsecure dependency on EF.Specification.Tests -->
<PackageVersion Include="System.Formats.Asn1" Version="8.0.1" />

<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<!-- <PackageVersion Include="xunit" Version="2.6.7-pre.5" />-->
<!-- <PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7-pre.8" />-->
<PackageVersion Include="xunit" Version="2.7.1" />
<PackageVersion Include="xunit.assert" Version="2.7.1" />
<PackageVersion Include="xunit.core" Version="2.7.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7" />
<PackageVersion Include="xunit" Version="2.8.1" />
<PackageVersion Include="xunit.assert" Version="2.8.1" />
<PackageVersion Include="xunit.core" Version="2.8.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.1" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public NpgsqlGeometryMemberTranslator(
_ => null
};

SqlFunctionExpression Function(string name, SqlExpression[] arguments, Type returnType, RelationalTypeMapping? typeMapping = null)
SqlExpression Function(string name, SqlExpression[] arguments, Type returnType, RelationalTypeMapping? typeMapping = null)
=> _sqlExpressionFactory.Function(
name, arguments,
nullable: true, argumentsPropagateNullability: TrueArrays[arguments.Length],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public NpgsqlGeometryMethodTranslator(
_ => null
};

SqlFunctionExpression Function(string name, SqlExpression[] arguments, Type returnType, RelationalTypeMapping? typeMapping = null)
SqlExpression Function(string name, SqlExpression[] arguments, Type returnType, RelationalTypeMapping? typeMapping = null)
=> _sqlExpressionFactory.Function(
name, arguments,
nullable: true, argumentsPropagateNullability: TrueArrays[arguments.Length],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal;
/// </summary>
public sealed class NpgsqlJsonGeometryWktReaderWriter : JsonValueReaderWriter<Geometry>
{
private static readonly PropertyInfo InstanceProperty = typeof(NpgsqlJsonGeometryWktReaderWriter).GetProperty(nameof(Instance))!;

private static readonly WKTReader WktReader = new();

/// <summary>
Expand All @@ -28,4 +30,7 @@ public override Geometry FromJsonTyped(ref Utf8JsonReaderManager manager, object
/// <inheritdoc />
public override void ToJsonTyped(Utf8JsonWriter writer, Geometry value)
=> writer.WriteStringValue(value.ToText());

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public NpgsqlNodaTimeMemberTranslator(
_ => null,
};

SqlBinaryExpression TranslateDurationTotalMember(SqlExpression instance, double divisor)
SqlExpression TranslateDurationTotalMember(SqlExpression instance, double divisor)
=> _sqlExpressionFactory.Divide(GetDatePartExpressionDouble(instance, "epoch"), _sqlExpressionFactory.Constant(divisor));
}

Expand Down
5 changes: 5 additions & 0 deletions src/EFCore.PG.NodaTime/Storage/Internal/DateMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ public override Expression GenerateCodeLiteral(object value)

private sealed class JsonLocalDateReaderWriter : JsonValueReaderWriter<LocalDate>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonLocalDateReaderWriter).GetProperty(nameof(Instance))!;

public static JsonLocalDateReaderWriter Instance { get; } = new();

public override LocalDate FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
Expand All @@ -138,5 +140,8 @@ public override LocalDate FromJsonTyped(ref Utf8JsonReaderManager manager, objec

public override void ToJsonTyped(Utf8JsonWriter writer, LocalDate value)
=> writer.WriteStringValue(FormatLocalDate(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,17 @@ void Compose(Expression toAdd)

private sealed class JsonDurationReaderWriter : JsonValueReaderWriter<Duration>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonDurationReaderWriter).GetProperty(nameof(Instance))!;

public static JsonDurationReaderWriter Instance { get; } = new();

public override Duration FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> Duration.FromTimeSpan(NpgsqlIntervalTypeMapping.ParseIntervalAsTimeSpan(manager.CurrentReader.GetString()!));

public override void ToJsonTyped(Utf8JsonWriter writer, Duration value)
=> writer.WriteStringValue(NpgsqlIntervalTypeMapping.FormatTimeSpanAsInterval(value.ToTimeSpan()));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,17 @@ void Compose(Expression toAdd)

private sealed class JsonPeriodReaderWriter : JsonValueReaderWriter<Period>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonPeriodReaderWriter).GetProperty(nameof(Instance))!;

public static JsonPeriodReaderWriter Instance { get; } = new();

public override Period FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> PeriodPattern.NormalizingIso.Parse(manager.CurrentReader.GetString()!).GetValueOrThrow();

public override void ToJsonTyped(Utf8JsonWriter writer, Period value)
=> writer.WriteStringValue(PeriodPattern.NormalizingIso.Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
5 changes: 5 additions & 0 deletions src/EFCore.PG.NodaTime/Storage/Internal/TimeMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,17 @@ public override Expression GenerateCodeLiteral(object value)

private sealed class JsonLocalTimeReaderWriter : JsonValueReaderWriter<LocalTime>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonLocalTimeReaderWriter).GetProperty(nameof(Instance))!;

public static JsonLocalTimeReaderWriter Instance { get; } = new();

public override LocalTime FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> LocalTimePattern.ExtendedIso.Parse(manager.CurrentReader.GetString()!).GetValueOrThrow();

public override void ToJsonTyped(Utf8JsonWriter writer, LocalTime value)
=> writer.WriteStringValue(LocalTimePattern.ExtendedIso.Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
5 changes: 5 additions & 0 deletions src/EFCore.PG.NodaTime/Storage/Internal/TimeTzMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,17 @@ public override Expression GenerateCodeLiteral(object value)

private sealed class JsonOffsetTimeReaderWriter : JsonValueReaderWriter<OffsetTime>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonOffsetTimeReaderWriter).GetProperty(nameof(Instance))!;

public static JsonOffsetTimeReaderWriter Instance { get; } = new();

public override OffsetTime FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> Pattern.Parse(manager.CurrentReader.GetString()!).GetValueOrThrow();

public override void ToJsonTyped(Utf8JsonWriter writer, OffsetTime value)
=> writer.WriteStringValue(Pattern.Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ internal static Expression GenerateCodeLiteral(LocalDateTime dateTime)

private sealed class JsonLocalDateTimeReaderWriter : JsonValueReaderWriter<LocalDateTime>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonLocalDateTimeReaderWriter).GetProperty(nameof(Instance))!;

public static JsonLocalDateTimeReaderWriter Instance { get; } = new();

public override LocalDateTime FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
Expand All @@ -165,5 +167,8 @@ public override LocalDateTime FromJsonTyped(ref Utf8JsonReaderManager manager, o

public override void ToJsonTyped(Utf8JsonWriter writer, LocalDateTime value)
=> writer.WriteStringValue(Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ private static readonly MethodInfo _fromUnixTimeTicks

private sealed class JsonInstantReaderWriter : JsonValueReaderWriter<Instant>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonInstantReaderWriter).GetProperty(nameof(Instance))!;

public static JsonInstantReaderWriter Instance { get; } = new();

public override Instant FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
Expand All @@ -147,5 +149,8 @@ public override Instant FromJsonTyped(ref Utf8JsonReaderManager manager, object?

public override void ToJsonTyped(Utf8JsonWriter writer, Instant value)
=> writer.WriteStringValue(Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,17 @@ public override Expression GenerateCodeLiteral(object value)

private sealed class JsonOffsetDateTimeReaderWriter : JsonValueReaderWriter<OffsetDateTime>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonOffsetDateTimeReaderWriter).GetProperty(nameof(Instance))!;

public static JsonOffsetDateTimeReaderWriter Instance { get; } = new();

public override OffsetDateTime FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> OffsetDateTimePattern.ExtendedIso.Parse(manager.CurrentReader.GetString()!).GetValueOrThrow();

public override void ToJsonTyped(Utf8JsonWriter writer, OffsetDateTime value)
=> writer.WriteStringValue(Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,17 @@ public override Expression GenerateCodeLiteral(object value)

private sealed class JsonZonedDateTimeReaderWriter : JsonValueReaderWriter<ZonedDateTime>
{
private static readonly PropertyInfo InstanceProperty = typeof(JsonZonedDateTimeReaderWriter).GetProperty(nameof(Instance))!;

public static JsonZonedDateTimeReaderWriter Instance { get; } = new();

public override ZonedDateTime FromJsonTyped(ref Utf8JsonReaderManager manager, object? existingObject = null)
=> Pattern.Parse(manager.CurrentReader.GetString()!).GetValueOrThrow();

public override void ToJsonTyped(Utf8JsonWriter writer, ZonedDateTime value)
=> writer.WriteStringValue(Pattern.Format(value));

/// <inheritdoc />
public override Expression ConstructorExpression => Expression.Property(null, InstanceProperty);
}
}
2 changes: 1 addition & 1 deletion src/EFCore.PG/EFCore.PG.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Description>PostgreSQL/Npgsql provider for Entity Framework Core.</Description>
<PackageTags>npgsql;postgresql;postgres;Entity Framework Core;entity-framework-core;ef;efcore;orm;sql</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<NoWarn>EF1003</NoWarn> <!-- Precompiled query is experimental -->
<NoWarn>EF9100</NoWarn> <!-- Precompiled query is experimental -->
</PropertyGroup>

<ItemGroup>
Expand Down
104 changes: 100 additions & 4 deletions src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,81 @@ public NpgsqlHistoryRepository(HistoryRepositoryDependencies dependencies)
{
}

// TODO: We override Exists() as a workaround for https://github.com/dotnet/efcore/issues/34569; this should be fixed on the EF side
// before EF 9.0 is released

/// <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
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override bool Exists()
=> Dependencies.DatabaseCreator.Exists()
&& InterpretExistsResult(
Dependencies.RawSqlCommandBuilder.Build(ExistsSql).ExecuteScalar(
new RelationalCommandParameterObject(
Dependencies.Connection,
null,
null,
Dependencies.CurrentContext.Context,
Dependencies.CommandLogger, CommandSource.Migrations)));

/// <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
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override async Task<bool> ExistsAsync(CancellationToken cancellationToken = default)
=> await Dependencies.DatabaseCreator.ExistsAsync(cancellationToken).ConfigureAwait(false)
&& InterpretExistsResult(
await Dependencies.RawSqlCommandBuilder.Build(ExistsSql).ExecuteScalarAsync(
new RelationalCommandParameterObject(
Dependencies.Connection,
null,
null,
Dependencies.CurrentContext.Context,
Dependencies.CommandLogger, CommandSource.Migrations),
cancellationToken).ConfigureAwait(false));

/// <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
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override IDisposable GetDatabaseLock(TimeSpan timeout)
{
// TODO: There are issues with the current lock implementation in EF - most importantly, the lock isn't acquired within a
// transaction so we can't use e.g. LOCK TABLE. This should be fixed for rc.1, see #34439.

// Dependencies.RawSqlCommandBuilder
// .Build($"LOCK TABLE {Dependencies.SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema)} IN ACCESS EXCLUSIVE MODE")
// .ExecuteNonQuery(CreateRelationalCommandParameters());

return new DummyDisposable();
}

/// <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
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override Task<IAsyncDisposable> GetDatabaseLockAsync(TimeSpan timeout, CancellationToken cancellationToken = default)
{
// TODO: There are issues with the current lock implementation in EF - most importantly, the lock isn't acquired within a
// transaction so we can't use e.g. LOCK TABLE. This should be fixed for rc.1, see #34439.

// await Dependencies.RawSqlCommandBuilder
// .Build($"LOCK TABLE {Dependencies.SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema)} IN ACCESS EXCLUSIVE MODE")
// .ExecuteNonQueryAsync(CreateRelationalCommandParameters(), cancellationToken)
// .ConfigureAwait(false);

return Task.FromResult<IAsyncDisposable>(new DummyDisposable());
}

/// <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 @@ -83,10 +158,11 @@ public override string GetBeginIfNotExistsScript(string migrationId)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override string GetBeginIfExistsScript(string migrationId)
=> $@"
=> $"""
DO $EF$
BEGIN
IF EXISTS(SELECT 1 FROM {SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema)} WHERE ""{MigrationIdColumnName}"" = '{migrationId}') THEN";
IF EXISTS(SELECT 1 FROM {SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema)} WHERE "{MigrationIdColumnName}" = '{migrationId}') THEN
""";

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -95,6 +171,26 @@ public override string GetBeginIfExistsScript(string migrationId)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override string GetEndIfScript()
=> @" END IF;
END $EF$;";
=> """
END IF;
END $EF$;
""";

private RelationalCommandParameterObject CreateRelationalCommandParameters()
=> new(
Dependencies.Connection,
null,
null,
Dependencies.CurrentContext.Context,
Dependencies.CommandLogger, CommandSource.Migrations);

private sealed class DummyDisposable : IDisposable, IAsyncDisposable
{
public void Dispose()
{
}

public ValueTask DisposeAsync()
=> default;
}
}
Loading

0 comments on commit f3fb1a6

Please sign in to comment.