diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8c6d4bc99..242f8e6f6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,7 +11,7 @@ on:
pull_request:
env:
- dotnet_sdk_version: '9.0.100-preview.7.24407.12'
+ dotnet_sdk_version: '9.0.100-rc.1.24451.4'
postgis_version: 3
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 9f6bdb73b..31920ab09 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -27,7 +27,7 @@ on:
- cron: '30 22 * * 6'
env:
- dotnet_sdk_version: '9.0.100-preview.7.24407.12'
+ dotnet_sdk_version: '9.0.100-rc.1.24451.4'
jobs:
analyze:
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 719cf3228..fd299fb25 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,7 +1,7 @@
- [9.0.0-preview.7.24405.3]
- 9.0.0-preview.7.24405.7
+ [9.0.0-rc.1.24451.1]
+ 9.0.0-rc.1.24431.7
8.0.3
@@ -21,15 +21,16 @@
-
+
+
-
-
-
-
+
+
+
+
diff --git a/global.json b/global.json
index a143424dc..8fcf651cb 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.100-preview.7.24407.12",
+ "version": "9.0.100-rc.1.24451.4",
"rollForward": "latestMajor",
"allowPrerelease": true
}
diff --git a/src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs b/src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
index beaf86d7c..5fadf3eba 100644
--- a/src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
+++ b/src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs
@@ -63,7 +63,7 @@ await Dependencies.RawSqlCommandBuilder.Build(ExistsSql).ExecuteScalarAsync(
/// 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.
///
- public override IDisposable GetDatabaseLock(TimeSpan timeout)
+ public override IDisposable GetDatabaseLock()
{
// 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.
@@ -81,7 +81,7 @@ public override IDisposable GetDatabaseLock(TimeSpan timeout)
/// 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.
///
- public override Task GetDatabaseLockAsync(TimeSpan timeout, CancellationToken cancellationToken = default)
+ public override Task GetDatabaseLockAsync(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.
diff --git a/src/EFCore.PG/Migrations/Internal/NpgsqlMigrator.cs b/src/EFCore.PG/Migrations/Internal/NpgsqlMigrator.cs
index 6b7d1f16b..cf8d222c5 100644
--- a/src/EFCore.PG/Migrations/Internal/NpgsqlMigrator.cs
+++ b/src/EFCore.PG/Migrations/Internal/NpgsqlMigrator.cs
@@ -36,10 +36,13 @@ public NpgsqlMigrator(
IModelRuntimeInitializer modelRuntimeInitializer,
IDiagnosticsLogger logger,
IRelationalCommandDiagnosticsLogger commandLogger,
- IDatabaseProvider databaseProvider)
+ IDatabaseProvider databaseProvider,
+ IMigrationsModelDiffer migrationsModelDiffer,
+ IDesignTimeModel designTimeModel,
+ IDbContextOptions contextOptions)
: base(migrationsAssembly, historyRepository, databaseCreator, migrationsSqlGenerator, rawSqlCommandBuilder,
migrationCommandExecutor, connection, sqlGenerationHelper, currentContext, modelRuntimeInitializer, logger,
- commandLogger, databaseProvider)
+ commandLogger, databaseProvider, migrationsModelDiffer, designTimeModel, contextOptions)
{
_historyRepository = historyRepository;
_connection = connection;
@@ -51,7 +54,7 @@ public NpgsqlMigrator(
/// 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.
///
- public override void Migrate(string? targetMigration = null)
+ public override void Migrate(string? targetMigration)
{
var appliedMigrations = _historyRepository.GetAppliedMigrations();
@@ -60,17 +63,15 @@ public override void Migrate(string? targetMigration = null)
PopulateMigrations(
appliedMigrations.Select(t => t.MigrationId),
targetMigration,
- out var migrationsToApply,
- out var migrationsToRevert,
- out _);
+ out var migratorData);
- if (migrationsToRevert.Count + migrationsToApply.Count == 0)
+ if (migratorData.RevertedMigrations.Count + migratorData.AppliedMigrations.Count == 0)
{
return;
}
// If a PostgreSQL extension, enum or range was added, we want Npgsql to reload all types at the ADO.NET level.
- var migrations = migrationsToApply.Count > 0 ? migrationsToApply : migrationsToRevert;
+ var migrations = migratorData.AppliedMigrations.Count > 0 ? migratorData.AppliedMigrations : migratorData.RevertedMigrations;
var reloadTypes = migrations
.SelectMany(m => m.UpOperations)
.OfType()
@@ -96,9 +97,7 @@ public override void Migrate(string? targetMigration = null)
/// 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.
///
- public override async Task MigrateAsync(
- string? targetMigration = null,
- CancellationToken cancellationToken = default)
+ public override async Task MigrateAsync(string? targetMigration, CancellationToken cancellationToken = default)
{
var appliedMigrations = await _historyRepository.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false);
@@ -107,17 +106,15 @@ public override async Task MigrateAsync(
PopulateMigrations(
appliedMigrations.Select(t => t.MigrationId),
targetMigration,
- out var migrationsToApply,
- out var migrationsToRevert,
- out _);
+ out var migratorData);
- if (migrationsToRevert.Count + migrationsToApply.Count == 0)
+ if (migratorData.RevertedMigrations.Count + migratorData.AppliedMigrations.Count == 0)
{
return;
}
// If a PostgreSQL extension, enum or range was added, we want Npgsql to reload all types at the ADO.NET level.
- var migrations = migrationsToApply.Count > 0 ? migrationsToApply : migrationsToRevert;
+ var migrations = migratorData.AppliedMigrations.Count > 0 ? migratorData.AppliedMigrations : migratorData.RevertedMigrations;
var reloadTypes = migrations
.SelectMany(m => m.UpOperations)
.OfType()
diff --git a/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessor.cs b/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessor.cs
index c79480a72..dbb97a5c4 100644
--- a/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessor.cs
+++ b/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessor.cs
@@ -16,8 +16,8 @@ public class NpgsqlParameterBasedSqlProcessor : RelationalParameterBasedSqlProce
///
public NpgsqlParameterBasedSqlProcessor(
RelationalParameterBasedSqlProcessorDependencies dependencies,
- bool useRelationalNulls)
- : base(dependencies, useRelationalNulls)
+ RelationalParameterBasedSqlProcessorParameters parameters)
+ : base(dependencies, parameters)
{
}
@@ -48,7 +48,7 @@ protected override Expression ProcessSqlNullability(
Check.NotNull(selectExpression, nameof(selectExpression));
Check.NotNull(parametersValues, nameof(parametersValues));
- return new NpgsqlSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process(
+ return new NpgsqlSqlNullabilityProcessor(Dependencies, Parameters).Process(
selectExpression, parametersValues, out canCache);
}
}
diff --git a/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessorFactory.cs b/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessorFactory.cs
index d3d0d342d..fa467d127 100644
--- a/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessorFactory.cs
+++ b/src/EFCore.PG/Query/Internal/NpgsqlParameterBasedSqlProcessorFactory.cs
@@ -23,11 +23,10 @@ public NpgsqlParameterBasedSqlProcessorFactory(
}
///
- /// 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.
+ /// Creates a new .
///
- public virtual RelationalParameterBasedSqlProcessor Create(bool useRelationalNulls)
- => new NpgsqlParameterBasedSqlProcessor(_dependencies, useRelationalNulls);
+ /// Parameters for .
+ /// A relational parameter based sql processor.
+ public RelationalParameterBasedSqlProcessor Create(RelationalParameterBasedSqlProcessorParameters parameters)
+ => new NpgsqlParameterBasedSqlProcessor(_dependencies, parameters);
}
diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
index e81ebcf0a..a6d4a6871 100644
--- a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
+++ b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
@@ -767,6 +767,11 @@ protected override Expression VisitValues(ValuesExpression valuesExpression)
///
protected override void GenerateValues(ValuesExpression valuesExpression)
{
+ if (valuesExpression.RowValues is null)
+ {
+ throw new UnreachableException();
+ }
+
if (valuesExpression.RowValues.Count == 0)
{
throw new InvalidOperationException(RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot);
diff --git a/src/EFCore.PG/Query/Internal/NpgsqlSqlNullabilityProcessor.cs b/src/EFCore.PG/Query/Internal/NpgsqlSqlNullabilityProcessor.cs
index 09644eb44..215219f19 100644
--- a/src/EFCore.PG/Query/Internal/NpgsqlSqlNullabilityProcessor.cs
+++ b/src/EFCore.PG/Query/Internal/NpgsqlSqlNullabilityProcessor.cs
@@ -11,14 +11,15 @@ public class NpgsqlSqlNullabilityProcessor : SqlNullabilityProcessor
private readonly ISqlExpressionFactory _sqlExpressionFactory;
///
- /// Creates a new instance of the class.
+ /// 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.
///
- /// Parameter object containing dependencies for this class.
- /// A bool value indicating whether relational null semantics are in use.
public NpgsqlSqlNullabilityProcessor(
RelationalParameterBasedSqlProcessorDependencies dependencies,
- bool useRelationalNulls)
- : base(dependencies, useRelationalNulls)
+ RelationalParameterBasedSqlProcessorParameters parameters)
+ : base(dependencies, parameters)
{
_sqlExpressionFactory = dependencies.SqlExpressionFactory;
}
@@ -101,7 +102,7 @@ SqlExpression VisitRowValueComparison(
// visit that (that adds the compensation). We then chain all such expressions together with AND.
var valueBinaryExpression = Visit(
_sqlExpressionFactory.MakeBinary(
- operatorType, visitedLeftValue, visitedRightValue, typeMapping: null, existingExpr: sqlBinaryExpression)!,
+ operatorType, visitedLeftValue, visitedRightValue, typeMapping: null, existingExpression: sqlBinaryExpression)!,
allowOptimizedExpansion,
out _);
@@ -144,7 +145,7 @@ visitedRightValues is null
? rightRowValue
: new PgRowValueExpression(visitedRightValues, leftRowValue.Type, leftRowValue.TypeMapping),
typeMapping: null,
- existingExpr: sqlBinaryExpression)!;
+ existingExpression: sqlBinaryExpression)!;
}
Check.DebugAssert(visitedLeftValues is not null, "visitedLeftValues is not null");
diff --git a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
index 084ec149f..4011ace02 100644
--- a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
+++ b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
@@ -21,6 +21,7 @@
+
diff --git a/test/EFCore.PG.FunctionalTests/ExecutionStrategyTest.cs b/test/EFCore.PG.FunctionalTests/ExecutionStrategyTest.cs
index f66ac9433..640b3c356 100644
--- a/test/EFCore.PG.FunctionalTests/ExecutionStrategyTest.cs
+++ b/test/EFCore.PG.FunctionalTests/ExecutionStrategyTest.cs
@@ -99,7 +99,7 @@ private void Test_commit_failure(bool realFailure, Action l.Id == CoreEventId.ExecutionStrategyRetrying));
+ Assert.DoesNotContain(Fixture.TestSqlLoggerFactory.Log, l => l.Id == CoreEventId.ExecutionStrategyRetrying);
}
Assert.Equal(realFailure ? 3 : 2, connection.OpenCount);
@@ -213,7 +213,7 @@ private async Task Test_commit_failure_async(
}
else
{
- Assert.Empty(Fixture.TestSqlLoggerFactory.Log.Where(l => l.Id == CoreEventId.ExecutionStrategyRetrying));
+ Assert.DoesNotContain(Fixture.TestSqlLoggerFactory.Log, l => l.Id == CoreEventId.ExecutionStrategyRetrying);
}
Assert.Equal(realFailure ? 3 : 2, connection.OpenCount);
diff --git a/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs
index d5307dbbd..6806f8fa0 100644
--- a/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/JsonTypesNpgsqlTest.cs
@@ -6,6 +6,7 @@
using System.Numerics;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
+using Xunit.Sdk;
namespace Npgsql.EntityFrameworkCore.PostgreSQL;
@@ -17,76 +18,76 @@ public class JsonTypesNpgsqlTest : JsonTypesRelationalTestBase
// supported).
public override Task Can_read_write_array_of_array_of_array_of_int_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_array_of_array_of_int_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_array_of_array_of_int_JSON_values());
public override Task Can_read_write_array_of_list_of_array_of_IPAddress_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_array_of_IPAddress_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_array_of_IPAddress_JSON_values());
public override Task Can_read_write_array_of_list_of_array_of_string_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_array_of_string_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_array_of_string_JSON_values());
public override Task Can_read_write_array_of_list_of_binary_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_binary_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_binary_JSON_values(expected));
public override Task Can_read_write_array_of_list_of_GUID_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_GUID_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_GUID_JSON_values(expected));
public override Task Can_read_write_array_of_list_of_int_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_int_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_int_JSON_values());
public override Task Can_read_write_array_of_list_of_IPAddress_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_IPAddress_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_IPAddress_JSON_values());
public override Task Can_read_write_array_of_list_of_string_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_string_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_string_JSON_values());
public override Task Can_read_write_array_of_list_of_ulong_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_ulong_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_array_of_list_of_ulong_JSON_values());
public override Task Can_read_write_list_of_array_of_GUID_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_GUID_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_GUID_JSON_values(expected));
public override Task Can_read_write_list_of_array_of_int_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_int_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_int_JSON_values());
public override Task Can_read_write_list_of_array_of_IPAddress_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_IPAddress_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_IPAddress_JSON_values());
public override Task Can_read_write_list_of_array_of_list_of_array_of_binary_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_array_of_binary_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_array_of_binary_JSON_values(expected));
public override Task Can_read_write_list_of_array_of_list_of_IPAddress_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_IPAddress_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_IPAddress_JSON_values());
public override Task Can_read_write_list_of_array_of_list_of_string_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_string_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_string_JSON_values());
public override Task Can_read_write_list_of_array_of_list_of_ulong_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_ulong_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_list_of_ulong_JSON_values());
public override Task Can_read_write_list_of_array_of_nullable_GUID_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_GUID_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_GUID_JSON_values(expected));
public override Task Can_read_write_list_of_array_of_nullable_int_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_int_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_int_JSON_values());
public override Task Can_read_write_list_of_array_of_nullable_ulong_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_ulong_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_nullable_ulong_JSON_values());
public override Task Can_read_write_list_of_array_of_string_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_string_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_string_JSON_values());
public override Task Can_read_write_list_of_array_of_ulong_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_ulong_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_ulong_JSON_values());
public override Task Can_read_write_list_of_list_of_list_of_int_JSON_values()
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_list_of_list_of_int_JSON_values());
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_list_of_list_of_int_JSON_values());
#endregion Nested collections (unsupported)
// IEnumerable property
public override Task Can_read_write_list_of_array_of_binary_JSON_values(string expected)
- => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_binary_JSON_values(expected));
+ => Assert.ThrowsAsync(() => base.Can_read_write_list_of_array_of_binary_JSON_values(expected));
// public override Task Can_read_write_ulong_enum_JSON_values(EnumU64 value, string json)
// {
diff --git a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs
index 996e3402b..ba84d9a0a 100644
--- a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsInfrastructureNpgsqlTest.cs
@@ -58,7 +58,8 @@ public async Task Empty_Migration_Creates_Database()
{
await using var context = new BloggingContext(
Fixture.TestStore.AddProviderOptions(
- new DbContextOptionsBuilder().EnableServiceProviderCaching(false)).Options);
+ new DbContextOptionsBuilder().EnableServiceProviderCaching(false))
+ .ConfigureWarnings(e => e.Log(RelationalEventId.PendingModelChangesWarning)).Options);
var creator = (NpgsqlDatabaseCreator)context.GetService();
creator.RetryTimeout = TimeSpan.FromMinutes(10);
@@ -185,21 +186,14 @@ protected override ITestStoreFactory TestStoreFactory
public override MigrationsContext CreateContext()
{
var options = AddOptions(
- new DbContextOptionsBuilder()
+ TestStore.AddProviderOptions(new DbContextOptionsBuilder())
.UseNpgsql(
TestStore.ConnectionString, b => b.ApplyConfiguration()
- .CommandTimeout(NpgsqlTestStore.CommandTimeout)
- .SetPostgresVersion(TestEnvironment.PostgresVersion)
- .ReverseNullOrdering()))
- .UseInternalServiceProvider(CreateServiceProvider())
+ .SetPostgresVersion(TestEnvironment.PostgresVersion)))
+ .UseInternalServiceProvider(ServiceProvider)
.Options;
return new MigrationsContext(options);
}
-
- private static IServiceProvider CreateServiceProvider()
- => new ServiceCollection()
- .AddEntityFrameworkNpgsql()
- .BuildServiceProvider();
}
}
}
diff --git a/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs
index cec0ec78a..056aab9d1 100644
--- a/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/AdHocJsonQueryNpgsqlTest.cs
@@ -7,7 +7,7 @@ public class AdHocJsonQueryNpgsqlTest : AdHocJsonQueryTestBase
protected override ITestStoreFactory TestStoreFactory
=> NpgsqlTestStoreFactory.Instance;
- protected override async Task Seed29219(MyContext29219 ctx)
+ protected override async Task Seed29219(DbContext ctx)
{
var entity1 = new MyEntity29219
{
@@ -28,7 +28,7 @@ protected override async Task Seed29219(MyContext29219 ctx)
Collection = [new() { NonNullableScalar = 1001, NullableScalar = null }]
};
- ctx.Entities.AddRange(entity1, entity2);
+ ctx.AddRange(entity1, entity2);
await ctx.SaveChangesAsync();
await ctx.Database.ExecuteSqlAsync(
@@ -38,7 +38,7 @@ await ctx.Database.ExecuteSqlAsync(
""");
}
- protected override async Task Seed30028(MyContext30028 ctx)
+ protected override async Task Seed30028(DbContext ctx)
{
// complete
await ctx.Database.ExecuteSqlAsync(
@@ -77,14 +77,14 @@ await ctx.Database.ExecuteSqlAsync(
""");
}
- protected override async Task Seed33046(Context33046 ctx)
+ protected override async Task Seed33046(DbContext ctx)
=> await ctx.Database.ExecuteSqlAsync(
$$"""
INSERT INTO "Reviews" ("Rounds", "Id")
VALUES('[{"RoundNumber":11,"SubRounds":[{"SubRoundNumber":111},{"SubRoundNumber":112}]}]', 1)
""");
- protected override async Task SeedArrayOfPrimitives(MyContextArrayOfPrimitives ctx)
+ protected override async Task SeedArrayOfPrimitives(DbContext ctx)
{
var entity1 = new MyEntityArrayOfPrimitives
{
@@ -126,11 +126,11 @@ protected override async Task SeedArrayOfPrimitives(MyContextArrayOfPrimitives c
]
};
- ctx.Entities.AddRange(entity1, entity2);
+ ctx.AddRange(entity1, entity2);
await ctx.SaveChangesAsync();
}
- protected override async Task SeedJunkInJson(MyContextJunkInJson ctx)
+ protected override async Task SeedJunkInJson(DbContext ctx)
=> await ctx.Database.ExecuteSqlAsync(
$$$"""
INSERT INTO "Entities" ("Collection", "CollectionWithCtor", "Reference", "ReferenceWithCtor", "Id")
@@ -142,7 +142,7 @@ protected override async Task SeedJunkInJson(MyContextJunkInJson ctx)
1)
""");
- protected override async Task SeedTrickyBuffering(MyContextTrickyBuffering ctx)
+ protected override async Task SeedTrickyBuffering(DbContext ctx)
=> await ctx.Database.ExecuteSqlAsync(
$$$"""
INSERT INTO "Entities" ("Reference", "Id")
@@ -150,7 +150,7 @@ protected override async Task SeedTrickyBuffering(MyContextTrickyBuffering ctx)
'{"Name": "r1", "Number": 7, "JunkReference":{"Something": "SomeValue" }, "JunkCollection": [{"Foo": "junk value"}], "NestedReference": {"DoB": "2000-01-01T00:00:00Z"}, "NestedCollection": [{"DoB": "2000-02-01T00:00:00Z", "JunkReference": {"Something": "SomeValue"}}, {"DoB": "2000-02-02T00:00:00Z"}]}',1)
""");
- protected override async Task SeedShadowProperties(MyContextShadowProperties ctx)
+ protected override async Task SeedShadowProperties(DbContext ctx)
=> await ctx.Database.ExecuteSqlAsync(
$$"""
INSERT INTO "Entities" ("Collection", "CollectionWithCtor", "Reference", "ReferenceWithCtor", "Id", "Name")
@@ -163,7 +163,7 @@ protected override async Task SeedShadowProperties(MyContextShadowProperties ctx
'e1')
""");
- protected override async Task SeedNotICollection(MyContextNotICollection ctx)
+ protected override async Task SeedNotICollection(DbContext ctx)
{
await ctx.Database.ExecuteSqlAsync(
$$"""
diff --git a/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs
index 9af98af68..e4706b39b 100644
--- a/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/JsonQueryNpgsqlTest.cs
@@ -3,7 +3,7 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query;
-public class JsonQueryNpgsqlTest : JsonQueryTestBase
+public class JsonQueryNpgsqlTest : JsonQueryRelationalTestBase
{
public JsonQueryNpgsqlTest(JsonQueryNpgsqlFixture fixture, ITestOutputHelper testOutputHelper)
: base(fixture)
@@ -3370,7 +3370,7 @@ public virtual void Check_all_tests_overridden()
private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
- public class JsonQueryNpgsqlFixture : JsonQueryFixtureBase, IQueryFixtureBase
+ public class JsonQueryNpgsqlFixture : JsonQueryRelationalFixture, IQueryFixtureBase
{
protected override ITestStoreFactory TestStoreFactory
=> NpgsqlTestStoreFactory.Instance;
diff --git a/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs
index fa4e4ab1b..399c8cd84 100644
--- a/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs
@@ -1,3 +1,4 @@
+using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
@@ -95,6 +96,20 @@ LIMIT 2
""");
}
+ protected override DbContextOptionsBuilder SetTranslateParameterizedCollectionsToConstants(DbContextOptionsBuilder optionsBuilder)
+ {
+ new NpgsqlDbContextOptionsBuilder(optionsBuilder).TranslateParameterizedCollectionsToConstants();
+
+ return optionsBuilder;
+ }
+
+ protected override DbContextOptionsBuilder SetTranslateParameterizedCollectionsToParameters(DbContextOptionsBuilder optionsBuilder)
+ {
+ new NpgsqlDbContextOptionsBuilder(optionsBuilder).TranslateParameterizedCollectionsToParameters();
+
+ return optionsBuilder;
+ }
+
protected override ITestStoreFactory TestStoreFactory
=> NpgsqlTestStoreFactory.Instance;
}
diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindAggregateOperatorsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindAggregateOperatorsQueryNpgsqlTest.cs
index e5dc276ad..6765d9481 100644
--- a/test/EFCore.PG.FunctionalTests/Query/NorthwindAggregateOperatorsQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindAggregateOperatorsQueryNpgsqlTest.cs
@@ -16,14 +16,33 @@ public NorthwindAggregateOperatorsQueryNpgsqlTest(
}
// Overriding to add equality tolerance because of floating point precision
- [ConditionalTheory]
- [MemberData(nameof(IsAsyncData))]
- public override Task Average_over_max_subquery_is_client_eval(bool async)
- => AssertAverage(
+ public override async Task Average_over_max_subquery(bool async)
+ {
+ await AssertAverage(
async,
ss => ss.Set().OrderBy(c => c.CustomerID).Take(3),
selector: c => (decimal)c.Orders.Average(o => 5 + o.OrderDetails.Max(od => od.ProductID)),
- asserter: (a, b) => Assert.Equal(a, b, 15));
+ asserter: (e, a) => Assert.Equal(e, a, 10));
+
+ AssertSql(
+ """
+@__p_0='3'
+
+SELECT avg((
+ SELECT avg(CAST(5 + (
+ SELECT max(o0."ProductID")
+ FROM "Order Details" AS o0
+ WHERE o."OrderID" = o0."OrderID") AS double precision))
+ FROM "Orders" AS o
+ WHERE c0."CustomerID" = o."CustomerID")::numeric)
+FROM (
+ SELECT c."CustomerID"
+ FROM "Customers" AS c
+ ORDER BY c."CustomerID" NULLS FIRST
+ LIMIT @__p_0
+) AS c0
+""");
+ }
public override async Task Contains_with_local_uint_array_closure(bool async)
{
diff --git a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs
index 9b8cd9926..7802ed3e7 100644
--- a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs
@@ -148,18 +148,6 @@ public override async Task Inline_collection_Contains_with_three_values(bool asy
""");
}
- public override async Task Inline_collection_Contains_with_EF_Constant(bool async)
- {
- await base.Inline_collection_Contains_with_EF_Constant(async);
-
- AssertSql(
- """
-SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
-FROM "PrimitiveCollectionsEntity" AS p
-WHERE p."Id" IN (2, 999, 1000)
-""");
- }
-
public override async Task Inline_collection_Contains_with_all_parameters(bool async)
{
await base.Inline_collection_Contains_with_all_parameters(async);
@@ -397,6 +385,68 @@ WHERE GREATEST(30, p."NullableInt", NULL) = 30
""");
}
+ public override async Task Inline_collection_with_single_parameter_element_Contains(bool async)
+ {
+ await base.Inline_collection_with_single_parameter_element_Contains(async);
+
+ AssertSql(
+ """
+@__i_0='2'
+
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE p."Id" = @__i_0
+""");
+ }
+
+ public override async Task Inline_collection_with_single_parameter_element_Count(bool async)
+ {
+ await base.Inline_collection_with_single_parameter_element_Count(async);
+
+ AssertSql(
+ """
+@__i_0='2'
+
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE (
+ SELECT count(*)::int
+ FROM (VALUES (@__i_0::int)) AS v("Value")
+ WHERE v."Value" > p."Id") = 1
+""");
+ }
+
+ public override async Task Inline_collection_Contains_with_EF_Parameter(bool async)
+ {
+ await base.Inline_collection_Contains_with_EF_Parameter(async);
+
+ AssertSql(
+ """
+@__p_0={ '2', '999', '1000' } (DbType = Object)
+
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE p."Id" = ANY (@__p_0)
+""");
+ }
+
+ public override async Task Inline_collection_Count_with_column_predicate_with_EF_Parameter(bool async)
+ {
+ await base.Inline_collection_Count_with_column_predicate_with_EF_Parameter(async);
+
+ AssertSql(
+ """
+@__p_0={ '2', '999', '1000' } (DbType = Object)
+
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE (
+ SELECT count(*)::int
+ FROM unnest(@__p_0) AS p0(value)
+ WHERE p0.value > p."Id") = 2
+""");
+ }
+
public override async Task Parameter_collection_Count(bool async)
{
await base.Parameter_collection_Count(async);
@@ -666,6 +716,48 @@ public override async Task Parameter_collection_null_Contains(bool async)
""");
}
+ public override async Task Parameter_collection_Contains_with_EF_Constant(bool async)
+ {
+ await base.Parameter_collection_Contains_with_EF_Constant(async);
+
+ AssertSql(
+ """
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE p."Id" IN (2, 999, 1000)
+""");
+ }
+
+ public override async Task Parameter_collection_Where_with_EF_Constant_Where_Any(bool async)
+ {
+ await base.Parameter_collection_Where_with_EF_Constant_Where_Any(async);
+
+ AssertSql(
+ """
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE EXISTS (
+ SELECT 1
+ FROM (VALUES (2), (999), (1000)) AS i("Value")
+ WHERE i."Value" > 0)
+""");
+ }
+
+ public override async Task Parameter_collection_Count_with_column_predicate_with_EF_Constant(bool async)
+ {
+ await base.Parameter_collection_Count_with_column_predicate_with_EF_Constant(async);
+
+ AssertSql(
+ """
+SELECT p."Id", p."Bool", p."Bools", p."DateTime", p."DateTimes", p."Enum", p."Enums", p."Int", p."Ints", p."NullableInt", p."NullableInts", p."NullableString", p."NullableStrings", p."String", p."Strings"
+FROM "PrimitiveCollectionsEntity" AS p
+WHERE (
+ SELECT count(*)::int
+ FROM (VALUES (2), (999), (1000)) AS i("Value")
+ WHERE i."Value" > p."Id") = 2
+""");
+ }
+
[ConditionalTheory] // #3012
[MinimumPostgresVersion(14, 0)] // Multiranges were introduced in PostgreSQL 14
[MemberData(nameof(IsAsyncData))]
diff --git a/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs b/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs
index c26bcc273..5696d082b 100644
--- a/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Scaffolding/NpgsqlDatabaseModelFactoryTest.cs
@@ -396,11 +396,11 @@ FOREIGN KEY ("ForeignKeyId1", "ForeignKeyId2") REFERENCES "db2"."PrincipalTable"
Assert.Equal("db2", sequence.Schema);
Assert.Single(dbModel.Tables.Where(t => t.Schema == "db.2" && t.Name == "QuotedTableName"));
- Assert.Empty(dbModel.Tables.Where(t => t.Schema == "db.2" && t.Name == "Table.With.Dot"));
+ Assert.DoesNotContain(dbModel.Tables, t => t.Schema == "db.2" && t.Name == "Table.With.Dot");
Assert.Single(dbModel.Tables.Where(t => t.Schema == "db.2" && t.Name == "SimpleTableName"));
Assert.Single(dbModel.Tables.Where(t => t.Schema == "db.2" && t.Name == "JustTableName"));
- Assert.Empty(dbModel.Tables.Where(t => t.Schema == "public" && t.Name == "QuotedTableName"));
+ Assert.DoesNotContain(dbModel.Tables, t => t.Schema == "public" && t.Name == "QuotedTableName");
Assert.Single(dbModel.Tables.Where(t => t.Schema == "public" && t.Name == "Table.With.Dot"));
Assert.Single(dbModel.Tables.Where(t => t.Schema == "public" && t.Name == "SimpleTableName"));
Assert.Single(dbModel.Tables.Where(t => t.Schema == "public" && t.Name == "JustTableName"));
diff --git a/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs
index 20dc78487..4db135758 100644
--- a/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Update/JsonUpdateNpgsqlTest.cs
@@ -1992,37 +1992,37 @@ public override Task Edit_single_property_relational_collection_of_nullable_enum
#region Skipped tests because of nested collections outside of JSON (nested arrays not supported in PG)
public override Task Edit_single_property_collection_of_collection_of_bool()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_char()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_double()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_int16()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_int32()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_int64()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_single()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_nullable_int32()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_nullable_int32_set_to_null()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_nullable_enum_set_to_null()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
public override Task Edit_single_property_collection_of_collection_of_nullable_enum_with_int_converter()
- => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
+ => Assert.ThrowsAsync(() => base.Edit_single_property_collection_of_collection_of_bool());
#endregion Skipped tests because of nested collections outside of JSON (nested arrays not supported in PG)