Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync to EF Core 9.0.0-preview.7.24405.3 #3258

Merged
merged 1 commit into from
Sep 1, 2024
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 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