diff --git a/src/EFCore.PG/Infrastructure/Internal/INpgsqlOptions.cs b/src/EFCore.PG/Infrastructure/Internal/INpgsqlOptions.cs
index 667825f62..605bddf38 100644
--- a/src/EFCore.PG/Infrastructure/Internal/INpgsqlOptions.cs
+++ b/src/EFCore.PG/Infrastructure/Internal/INpgsqlOptions.cs
@@ -14,6 +14,11 @@ public interface INpgsqlOptions : ISingletonOptions
///
Version PostgresVersion { get; }
+ ///
+ /// Whether to target Redshift.
+ ///
+ bool UseRedshift { get; }
+
///
/// True if reverse null ordering is enabled; otherwise, false.
///
diff --git a/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs b/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs
index 5d48a7739..ec50268d7 100644
--- a/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs
+++ b/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs
@@ -16,6 +16,8 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal
///
public class NpgsqlOptionsExtension : RelationalOptionsExtension
{
+ public static readonly Version DefaultPostgresVersion = new(12, 0);
+
private DbContextOptionsExtensionInfo? _info;
private readonly List _userRangeDefinitions;
@@ -27,7 +29,12 @@ public class NpgsqlOptionsExtension : RelationalOptionsExtension
///
/// The backend version to target.
///
- public virtual Version? PostgresVersion { get; private set; }
+ public virtual Version PostgresVersion { get; private set; } = DefaultPostgresVersion;
+
+ ///
+ /// Whether to target Redshift.
+ ///
+ public virtual bool UseRedshift { get; private set; }
///
/// The list of range mappings specified by the user.
@@ -132,7 +139,23 @@ public virtual NpgsqlOptionsExtension WithPostgresVersion(Version? postgresVersi
{
var clone = (NpgsqlOptionsExtension)Clone();
- clone.PostgresVersion = postgresVersion;
+ clone.PostgresVersion = postgresVersion ?? DefaultPostgresVersion;
+
+ return clone;
+ }
+
+ ///
+ /// Returns a copy of the current instance with the specified Redshift settings.
+ ///
+ /// Whether to target Redshift.
+ ///
+ /// A copy of the current instance with the specified Redshift setting.
+ ///
+ public virtual NpgsqlOptionsExtension WithRedshift(bool useRedshift)
+ {
+ var clone = (NpgsqlOptionsExtension)Clone();
+
+ clone.UseRedshift = useRedshift;
return clone;
}
@@ -150,6 +173,17 @@ internal virtual NpgsqlOptionsExtension WithReverseNullOrdering(bool reverseNull
return clone;
}
+ ///
+ public override void Validate(IDbContextOptions options)
+ {
+ base.Validate(options);
+
+ if (UseRedshift && !PostgresVersion.Equals(DefaultPostgresVersion))
+ {
+ throw new InvalidOperationException($"{nameof(UseRedshift)} and {nameof(PostgresVersion)} cannot both be set");
+ }
+ }
+
#region Authentication
///
@@ -234,11 +268,16 @@ public override string LogFragment
builder.Append(nameof(Extension.AdminDatabase)).Append("=").Append(Extension.AdminDatabase).Append(' ');
}
- if (Extension.PostgresVersion != null)
+ if (!Extension.PostgresVersion.Equals(DefaultPostgresVersion))
{
builder.Append(nameof(Extension.PostgresVersion)).Append("=").Append(Extension.PostgresVersion).Append(' ');
}
+ if (Extension.UseRedshift)
+ {
+ builder.Append(nameof(Extension.UseRedshift)).Append(' ');
+ }
+
if (Extension.ProvideClientCertificatesCallback != null)
{
builder.Append(nameof(Extension.ProvideClientCertificatesCallback)).Append(" ");
@@ -296,6 +335,7 @@ public override long GetServiceProviderHashCode()
(h, ud) => (h * 397) ^ ud.GetHashCode());
_serviceProviderHash = (_serviceProviderHash * 397) ^ Extension.AdminDatabase?.GetHashCode() ?? 0L;
_serviceProviderHash = (_serviceProviderHash * 397) ^ (Extension.PostgresVersion?.GetHashCode() ?? 0L);
+ _serviceProviderHash = (_serviceProviderHash * 397) ^ Extension.UseRedshift.GetHashCode();
_serviceProviderHash = (_serviceProviderHash * 397) ^ (Extension.ProvideClientCertificatesCallback?.GetHashCode() ?? 0L);
_serviceProviderHash = (_serviceProviderHash * 397) ^ (Extension.RemoteCertificateValidationCallback?.GetHashCode() ?? 0L);
_serviceProviderHash = (_serviceProviderHash * 397) ^ (Extension.ProvidePasswordCallback?.GetHashCode() ?? 0L);
@@ -315,6 +355,9 @@ public override void PopulateDebugInfo(IDictionary debugInfo)
debugInfo["Npgsql.EntityFrameworkCore.PostgreSQL:" + nameof(NpgsqlDbContextOptionsBuilder.SetPostgresVersion)]
= (Extension.PostgresVersion?.GetHashCode() ?? 0).ToString(CultureInfo.InvariantCulture);
+ debugInfo["Npgsql.EntityFrameworkCore.PostgreSQL:" + nameof(NpgsqlDbContextOptionsBuilder.UseRedshift)]
+ = Extension.UseRedshift.GetHashCode().ToString(CultureInfo.InvariantCulture);
+
debugInfo["Npgsql.EntityFrameworkCore.PostgreSQL:" + nameof(NpgsqlDbContextOptionsBuilder.ReverseNullOrdering)]
= Extension.ReverseNullOrdering.GetHashCode().ToString(CultureInfo.InvariantCulture);
@@ -338,7 +381,10 @@ public override void PopulateDebugInfo(IDictionary debugInfo)
#endregion Infrastructure
}
- public class UserRangeDefinition : IEquatable
+ ///
+ /// A definition for a user-defined PostgreSQL range to be mapped.
+ ///
+ public record UserRangeDefinition
{
///
/// The name of the PostgreSQL range type to be mapped.
@@ -374,30 +420,5 @@ public UserRangeDefinition(
SubtypeClrType = Check.NotNull(subtypeClrType, nameof(subtypeClrType));
SubtypeName = subtypeName;
}
-
- public override int GetHashCode()
- => HashCode.Combine(RangeName, SchemaName, SubtypeClrType, SubtypeName);
-
- public override bool Equals(object? obj) => obj is UserRangeDefinition urd && Equals(urd);
-
- public virtual bool Equals(UserRangeDefinition? other)
- => ReferenceEquals(this, other) ||
- !(other is null) &&
- RangeName == other.RangeName &&
- SchemaName == other.SchemaName &&
- SubtypeClrType == other.SubtypeClrType &&
- SubtypeName == other.SubtypeName;
-
- public virtual void Deconstruct(
- out string rangeName,
- out string? schemaName,
- out Type subtypeClrType,
- out string? subtypeName)
- {
- rangeName = RangeName;
- schemaName = SchemaName;
- subtypeClrType = SubtypeClrType;
- subtypeName = SubtypeName;
- }
}
}
diff --git a/src/EFCore.PG/Infrastructure/NpgsqlDbContextOptionsBuilder.cs b/src/EFCore.PG/Infrastructure/NpgsqlDbContextOptionsBuilder.cs
index 35c4e33a2..512782756 100644
--- a/src/EFCore.PG/Infrastructure/NpgsqlDbContextOptionsBuilder.cs
+++ b/src/EFCore.PG/Infrastructure/NpgsqlDbContextOptionsBuilder.cs
@@ -44,6 +44,14 @@ public virtual NpgsqlDbContextOptionsBuilder SetPostgresVersion(Version? postgre
public virtual NpgsqlDbContextOptionsBuilder SetPostgresVersion(int major, int minor)
=> SetPostgresVersion(new Version(major, minor));
+ ///
+ /// Configures the provider to work in Redshift compatibility mode, which avoids certain unsupported features from modern
+ /// PostgreSQL versions.
+ ///
+ /// Whether to target Redshift.
+ public virtual NpgsqlDbContextOptionsBuilder UseRedshift(bool useRedshift = true)
+ => WithOption(e => e.WithRedshift(useRedshift));
+
///
/// Maps a user-defined PostgreSQL range type for use.
///
diff --git a/src/EFCore.PG/Internal/NpgsqlOptions.cs b/src/EFCore.PG/Internal/NpgsqlOptions.cs
index d21777a8f..92323a212 100644
--- a/src/EFCore.PG/Internal/NpgsqlOptions.cs
+++ b/src/EFCore.PG/Internal/NpgsqlOptions.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -11,11 +12,12 @@ namespace Npgsql.EntityFrameworkCore.PostgreSQL.Internal
///
public class NpgsqlOptions : INpgsqlOptions
{
- public static readonly Version DefaultPostgresVersion = new(12, 0);
-
///
public virtual Version PostgresVersion { get; private set; } = null!;
+ ///
+ public virtual bool UseRedshift { get; private set; }
+
///
public virtual bool ReverseNullOrderingEnabled { get; private set; }
@@ -30,7 +32,8 @@ public virtual void Initialize(IDbContextOptions options)
{
var npgsqlOptions = options.FindExtension() ?? new NpgsqlOptionsExtension();
- PostgresVersion = npgsqlOptions.PostgresVersion ?? DefaultPostgresVersion;
+ PostgresVersion = npgsqlOptions.PostgresVersion;
+ UseRedshift = npgsqlOptions.UseRedshift;
ReverseNullOrderingEnabled = npgsqlOptions.ReverseNullOrdering;
UserRangeDefinitions = npgsqlOptions.UserRangeDefinitions;
}
@@ -40,6 +43,22 @@ public virtual void Validate(IDbContextOptions options)
{
var npgsqlOptions = options.FindExtension() ?? new NpgsqlOptionsExtension();
+ if (!PostgresVersion.Equals(npgsqlOptions.PostgresVersion))
+ {
+ throw new InvalidOperationException(
+ CoreStrings.SingletonOptionChanged(
+ nameof(NpgsqlDbContextOptionsBuilder.SetPostgresVersion),
+ nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
+ }
+
+ if (UseRedshift != npgsqlOptions.UseRedshift)
+ {
+ throw new InvalidOperationException(
+ CoreStrings.SingletonOptionChanged(
+ nameof(NpgsqlDbContextOptionsBuilder.UseRedshift),
+ nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
+ }
+
if (ReverseNullOrderingEnabled != npgsqlOptions.ReverseNullOrdering)
{
throw new InvalidOperationException(
@@ -47,6 +66,15 @@ public virtual void Validate(IDbContextOptions options)
nameof(NpgsqlDbContextOptionsBuilder.ReverseNullOrdering),
nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
}
+
+ if (UserRangeDefinitions.Count != npgsqlOptions.UserRangeDefinitions.Count
+ || UserRangeDefinitions.Zip(npgsqlOptions.UserRangeDefinitions).Any(t => t.First != t.Second))
+ {
+ throw new InvalidOperationException(
+ CoreStrings.SingletonOptionChanged(
+ nameof(NpgsqlDbContextOptionsBuilder.MapRange),
+ nameof(DbContextOptionsBuilder.UseInternalServiceProvider)));
+ }
}
}
}
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlArrayTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlArrayTranslator.cs
index 9f9ac21c7..2284c0473 100644
--- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlArrayTranslator.cs
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlArrayTranslator.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
@@ -35,18 +34,18 @@ public class NpgsqlArrayTranslator : IMethodCallTranslator, IMemberTranslator
typeof(Enumerable).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)
.Single(mi => mi.Name == nameof(Enumerable.Any) && mi.GetParameters().Length == 1);
- private readonly IRelationalTypeMappingSource _typeMappingSource;
private readonly NpgsqlSqlExpressionFactory _sqlExpressionFactory;
private readonly NpgsqlJsonPocoTranslator _jsonPocoTranslator;
+ private readonly bool _useRedshift;
public NpgsqlArrayTranslator(
- IRelationalTypeMappingSource typeMappingSource,
NpgsqlSqlExpressionFactory sqlExpressionFactory,
- NpgsqlJsonPocoTranslator jsonPocoTranslator)
+ NpgsqlJsonPocoTranslator jsonPocoTranslator,
+ bool useRedshift)
{
- _typeMappingSource = typeMappingSource;
_sqlExpressionFactory = sqlExpressionFactory;
_jsonPocoTranslator = jsonPocoTranslator;
+ _useRedshift = useRedshift;
}
public virtual SqlExpression? Translate(
@@ -94,8 +93,8 @@ static bool IsMappedToNonArray(SqlExpression arrayOrList)
if (method.IsClosedFormOf(EnumerableAnyWithoutPredicate))
{
return _sqlExpressionFactory.GreaterThan(
- _jsonPocoTranslator.TranslateArrayLength(arrayOrList) ??
- _sqlExpressionFactory.Function(
+ _jsonPocoTranslator.TranslateArrayLength(arrayOrList)
+ ?? _sqlExpressionFactory.Function(
"cardinality",
new[] { arrayOrList },
nullable: true,
@@ -108,17 +107,18 @@ static bool IsMappedToNonArray(SqlExpression arrayOrList)
// is pattern-matched in AllAnyToContainsRewritingExpressionVisitor, which transforms it to
// new[] { "a", "b", "c" }.Contains(e.Some Text).
- if ((method.IsClosedFormOf(EnumerableContains) || // Enumerable.Contains extension method
- method.Name == nameof(List.Contains) && method.DeclaringType.IsGenericList() &&
- method.GetParameters().Length == 1)
+ if ((method.IsClosedFormOf(EnumerableContains)
+ ||
+ method.Name == nameof(List.Contains)
+ && method.DeclaringType.IsGenericList()
+ && method.GetParameters().Length == 1)
&&
- (
- // Handle either array columns (with an array mapping) or parameters/constants (no mapping). We specifically
- // don't want to translate if the type mapping is bytea (CLR type is array, but not an array in
- // the database).
- // arrayOrList.TypeMapping == null && _typeMappingSource.FindMapping(arrayOrList.Type) != null ||
- arrayOrList.TypeMapping is NpgsqlArrayTypeMapping or null
- ))
+ // Handle either array columns (with an array mapping) or parameters/constants (no mapping). We specifically
+ // don't want to translate if the type mapping is bytea (CLR type is array, but not an array in
+ // the database).
+ // arrayOrList.TypeMapping == null && _typeMappingSource.FindMapping(arrayOrList.Type) != null ||
+ arrayOrList.TypeMapping is NpgsqlArrayTypeMapping or null
+ && !_useRedshift)
{
var item = arguments[0];
@@ -142,7 +142,8 @@ arrayOrList.TypeMapping is NpgsqlArrayTypeMapping or null
typeof(int)));
}
- return _sqlExpressionFactory.Contains(arrayOrList,
+ return _sqlExpressionFactory.Contains(
+ arrayOrList,
_sqlExpressionFactory.NewArrayOrConstant(new[] { item }, arrayOrList.Type));
// Don't do anything PG-specific for constant arrays since the general EF Core mechanism is fine
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMemberTranslatorProvider.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMemberTranslatorProvider.cs
index 42c29f67d..7426c313d 100644
--- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMemberTranslatorProvider.cs
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMemberTranslatorProvider.cs
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal
{
@@ -12,7 +13,8 @@ public class NpgsqlMemberTranslatorProvider : RelationalMemberTranslatorProvider
public NpgsqlMemberTranslatorProvider(
RelationalMemberTranslatorProviderDependencies dependencies,
- IRelationalTypeMappingSource typeMappingSource)
+ IRelationalTypeMappingSource typeMappingSource,
+ INpgsqlOptions npgsqlOptions)
: base(dependencies)
{
var sqlExpressionFactory = (NpgsqlSqlExpressionFactory)dependencies.SqlExpressionFactory;
@@ -20,7 +22,7 @@ public NpgsqlMemberTranslatorProvider(
AddTranslators(
new IMemberTranslator[] {
- new NpgsqlArrayTranslator(typeMappingSource, sqlExpressionFactory, JsonPocoTranslator),
+ new NpgsqlArrayTranslator(sqlExpressionFactory, JsonPocoTranslator, npgsqlOptions.UseRedshift),
new NpgsqlDateTimeMemberTranslator(sqlExpressionFactory),
new NpgsqlJsonDomTranslator(typeMappingSource, sqlExpressionFactory),
new NpgsqlLTreeTranslator(typeMappingSource, sqlExpressionFactory),
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMethodCallTranslatorProvider.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMethodCallTranslatorProvider.cs
index 6d2d0dbed..42b9f7803 100644
--- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMethodCallTranslatorProvider.cs
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMethodCallTranslatorProvider.cs
@@ -22,7 +22,7 @@ public NpgsqlMethodCallTranslatorProvider(
AddTranslators(new IMethodCallTranslator[]
{
- new NpgsqlArrayTranslator(typeMappingSource, npgsqlSqlExpressionFactory, jsonTranslator),
+ new NpgsqlArrayTranslator(npgsqlSqlExpressionFactory, jsonTranslator, npgsqlOptions.UseRedshift),
new NpgsqlByteArrayMethodTranslator(npgsqlSqlExpressionFactory),
new NpgsqlConvertTranslator(npgsqlSqlExpressionFactory),
new NpgsqlDateTimeMethodTranslator(typeMappingSource, npgsqlSqlExpressionFactory),
diff --git a/test/EFCore.PG.FunctionalTests/Query/CompatibilityQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/CompatibilityQueryNpgsqlTest.cs
index 24c377079..c86af0e65 100644
--- a/test/EFCore.PG.FunctionalTests/Query/CompatibilityQueryNpgsqlTest.cs
+++ b/test/EFCore.PG.FunctionalTests/Query/CompatibilityQueryNpgsqlTest.cs
@@ -1,7 +1,9 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.TestUtilities;
+using Microsoft.Extensions.DependencyInjection;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
using Xunit;
@@ -18,103 +20,103 @@ public CompatibilityQueryNpgsqlTest(CompatibilityQueryNpgsqlFixture fixture, ITe
{
Fixture = fixture;
Fixture.TestSqlLoggerFactory.Clear();
- //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
+ Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
}
- // CURRENTLY EMPTY
-
- private CompatibilityContext CreateContext(Version postgresVersion = null)
+ [ConditionalFact]
+ public async Task Array_contains_is_not_parameterized_with_array_on_redshift()
{
- var builder = new DbContextOptionsBuilder(Fixture.CreateOptions());
- if (postgresVersion != null)
- new NpgsqlDbContextOptionsBuilder(builder).SetPostgresVersion(postgresVersion);
- return new CompatibilityContext(builder.Options);
+ var ctx = CreateRedshiftContext();
+
+ var numbers = new[] { 8, 9 };
+ var result = await ctx.TestEntities.Where(e => numbers.Contains(e.SomeInt)).SingleAsync();
+ Assert.Equal(1, result.Id);
+
+ AssertSql(
+ @"SELECT t.""Id"", t.""SomeInt""
+FROM ""TestEntities"" AS t
+WHERE t.""SomeInt"" IN (8, 9)
+LIMIT 2");
}
- #region Fixtures
+ #region Support
- ///
- /// Represents a fixture suitable for testing backendVersion.
- ///
- public class CompatibilityQueryNpgsqlFixture : SharedStoreFixtureBase
+ private CompatibilityContext CreateContext(Version postgresVersion = null)
+ => Fixture.CreateContext(postgresVersion);
+
+ private CompatibilityContext CreateRedshiftContext()
+ => Fixture.CreateRedshiftContext();
+
+ public class CompatibilityQueryNpgsqlFixture : FixtureBase, IDisposable, IAsyncLifetime
{
- protected override string StoreName => "CompatibilityTest";
- protected override ITestStoreFactory TestStoreFactory => NpgsqlTestStoreFactory.Instance;
- public TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)ListLoggerFactory;
- protected override void Seed(CompatibilityContext context) => CompatibilityContext.Seed(context);
+ private TestStore _testStore;
+
+ private const string StoreName = "CompatibilityTest";
+ private readonly ListLoggerFactory _listLoggerFactory = NpgsqlTestStoreFactory.Instance.CreateListLoggerFactory(_ => false);
+ public TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)_listLoggerFactory;
+
+ public virtual CompatibilityContext CreateContext()
+ => CreateContext(null);
+
+ public virtual CompatibilityContext CreateContext(Version postgresVersion)
+ {
+ var builder = new DbContextOptionsBuilder();
+ _testStore.AddProviderOptions(builder);
+ builder
+ .UseNpgsql(o => o.SetPostgresVersion(postgresVersion))
+ .UseLoggerFactory(_listLoggerFactory);
+ return new CompatibilityContext(builder.Options);
+ }
+
+ public virtual CompatibilityContext CreateRedshiftContext()
+ {
+ var builder = new DbContextOptionsBuilder();
+ _testStore.AddProviderOptions(builder);
+ builder
+ .UseNpgsql(o => o.UseRedshift())
+ .UseLoggerFactory(_listLoggerFactory);
+ return new CompatibilityContext(builder.Options);
+ }
+
+ public virtual Task InitializeAsync()
+ {
+ _testStore = NpgsqlTestStoreFactory.Instance.GetOrCreate(StoreName);
+ _testStore.Initialize(null, CreateContext, c => CompatibilityContext.Seed((CompatibilityContext)c));
+ return Task.CompletedTask;
+ }
+
+ // Called after DisposeAsync
+ public virtual void Dispose()
+ {
+ }
+
+ public virtual Task DisposeAsync()
+ => _testStore.DisposeAsync();
}
- ///
- /// Represents an entity suitable for testing backendVersion.
- ///
public class CompatibilityTestEntity
{
- ///
- /// The primary key.
- ///
public int Id { get; set; }
-
- ///
- /// The date and time.
- ///
- public DateTime DateTime { get; set; }
+ public int SomeInt { get; set; }
}
- ///
- /// Represents a database suitable for testing range operators.
- ///
- public class CompatibilityContext : PoolableDbContext
+ public class CompatibilityContext : DbContext
{
- ///
- /// Represents a set of entities for backendVersion testing.
- ///
- public DbSet CompatibilityTestEntities { get; set; }
-
- ///
+ public DbSet TestEntities { get; set; }
public CompatibilityContext(DbContextOptions options) : base(options) {}
- ///
- protected override void OnModelCreating(ModelBuilder builder) {}
-
public static void Seed(CompatibilityContext context)
{
- context.CompatibilityTestEntities.AddRange(
- new CompatibilityTestEntity
- {
- Id = 1,
- DateTime = new DateTime(2018, 06, 23)
- },
- new CompatibilityTestEntity
- {
- Id = 2,
- DateTime = new DateTime(2018, 06, 23)
- },
- new CompatibilityTestEntity
- {
- Id = 3,
- DateTime = new DateTime(2018, 06, 23)
- });
-
+ context.TestEntities.AddRange(
+ new CompatibilityTestEntity { Id = 1, SomeInt = 8 },
+ new CompatibilityTestEntity { Id = 2, SomeInt = 10 });
context.SaveChanges();
}
}
- #endregion
-
- #region Helpers
-
- ///
- /// Asserts that the SQL fragment appears in the logs.
- ///
- /// The SQL statement or fragment to search for in the logs.
- private void AssertContainsSql(string sql) => Assert.Contains(sql, Fixture.TestSqlLoggerFactory.Sql);
-
- ///
- /// Asserts that the SQL fragment does not appears in the logs.
- ///
- /// The SQL statement or fragment to search for in the logs.
- private void AssertDoesNotContainsSql(string sql) => Assert.DoesNotContain(sql, Fixture.TestSqlLoggerFactory.Sql);
+ private void AssertSql(params string[] expected)
+ => Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
- #endregion
+ #endregion Support
}
}
diff --git a/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestHelpers.cs b/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestHelpers.cs
index a76638ce7..57fbd9970 100644
--- a/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestHelpers.cs
+++ b/test/EFCore.PG.FunctionalTests/TestUtilities/NpgsqlTestHelpers.cs
@@ -1,38 +1,13 @@
-using System;
-using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Microsoft.Extensions.DependencyInjection;
using Npgsql.EntityFrameworkCore.PostgreSQL.Diagnostics.Internal;
-using Xunit;
namespace Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities
{
public class NpgsqlTestHelpers : TestHelpers
{
- private Version _postgresVersion;
-
- public class VersionScope : IDisposable
- {
- private readonly NpgsqlTestHelpers _helpers;
- private readonly Version _oldVersion, _newVersion;
-
- internal VersionScope(NpgsqlTestHelpers helpers, Version version)
- {
- _helpers = helpers;
- _oldVersion = helpers._postgresVersion;
- _newVersion = helpers._postgresVersion = version;
- }
-
- public void Dispose()
- {
- Assert.Equal(_helpers._postgresVersion, _newVersion);
- _helpers._postgresVersion = _oldVersion;
- }
- }
-
- public VersionScope WithPostgresVersion(Version version) => new(this, version);
-
protected NpgsqlTestHelpers() {}
public static NpgsqlTestHelpers Instance { get; } = new();
@@ -41,8 +16,7 @@ public override IServiceCollection AddProviderServices(IServiceCollection servic
=> services.AddEntityFrameworkNpgsql();
public override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
- => optionsBuilder.UseNpgsql(new NpgsqlConnection("Host=localhost;Database=DummyDatabase"),
- options => options.SetPostgresVersion(_postgresVersion));
+ => optionsBuilder.UseNpgsql(new NpgsqlConnection("Host=localhost;Database=DummyDatabase"));
public override LoggingDefinitions LoggingDefinitions { get; } = new NpgsqlLoggingDefinitions();
}