diff --git a/Directory.Build.props b/Directory.Build.props index b26432baa..7fd283bf2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,7 +12,7 @@ Copyright 2021 © The Npgsql Development Team Npgsql - 6.0.0-preview7 + 6.0.0-rc.1 true PostgreSQL https://github.com/npgsql/efcore.pg diff --git a/Directory.Packages.props b/Directory.Packages.props index f78076e1f..84469498a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,7 +1,7 @@ - 6.0.0-preview.7.21378.4 - 6.0.0-preview.7.21377.19 + 6.0.0-rc.1.21406.1 + 6.0.0-rc.1.21401.3 6.0.0-preview6 diff --git a/src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs b/src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs index 53bc8cf8f..245721c8b 100644 --- a/src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs +++ b/src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs @@ -72,7 +72,10 @@ public ExtensionInfo(IDbContextOptionsExtension extension) public override bool IsDatabaseProvider => false; - public override long GetServiceProviderHashCode() => Extension.IsGeographyDefault.GetHashCode(); + public override int GetServiceProviderHashCode() => Extension.IsGeographyDefault.GetHashCode(); + + public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) + => true; public override void PopulateDebugInfo(IDictionary debugInfo) { diff --git a/src/EFCore.PG.NodaTime/Infrastructure/Internal/NpgsqlNodaTimeOptionsExtension.cs b/src/EFCore.PG.NodaTime/Infrastructure/Internal/NpgsqlNodaTimeOptionsExtension.cs index 2816a0bfe..f85930647 100644 --- a/src/EFCore.PG.NodaTime/Infrastructure/Internal/NpgsqlNodaTimeOptionsExtension.cs +++ b/src/EFCore.PG.NodaTime/Infrastructure/Internal/NpgsqlNodaTimeOptionsExtension.cs @@ -48,7 +48,10 @@ public ExtensionInfo(IDbContextOptionsExtension extension) public override bool IsDatabaseProvider => false; - public override long GetServiceProviderHashCode() => 0; + public override int GetServiceProviderHashCode() => 0; + + public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) + => true; public override void PopulateDebugInfo(IDictionary debugInfo) => debugInfo["Npgsql:" + nameof(NpgsqlNodaTimeDbContextOptionsBuilderExtensions.UseNodaTime)] = "1"; diff --git a/src/EFCore.PG/Extensions/MetadataExtensions/NpgsqlPropertyExtensions.cs b/src/EFCore.PG/Extensions/MetadataExtensions/NpgsqlPropertyExtensions.cs index 6bd127d4f..5911cc388 100644 --- a/src/EFCore.PG/Extensions/MetadataExtensions/NpgsqlPropertyExtensions.cs +++ b/src/EFCore.PG/Extensions/MetadataExtensions/NpgsqlPropertyExtensions.cs @@ -406,12 +406,12 @@ private static void CheckValueGenerationStrategy(IReadOnlyProperty property, Npg /// if compatible. public static bool IsCompatibleWithValueGeneration(IReadOnlyProperty property) { - var type = property.ClrType; + var valueConverter = property.GetValueConverter() + ?? property.FindTypeMapping()?.Converter; - return type.IsInteger() - && (property.GetValueConverter() - ?? property.FindTypeMapping()?.Converter) - == null; + var type = (valueConverter?.ProviderClrType ?? property.ClrType).UnwrapNullableType(); + + return type.IsInteger(); } private static bool IsCompatibleWithValueGeneration( @@ -419,13 +419,13 @@ private static bool IsCompatibleWithValueGeneration( in StoreObjectIdentifier storeObject, ITypeMappingSource? typeMappingSource) { - var type = property.ClrType; + var valueConverter = property.GetValueConverter() + ?? (property.FindRelationalTypeMapping(storeObject) + ?? typeMappingSource?.FindMapping((IProperty)property))?.Converter; + + var type = (valueConverter?.ProviderClrType ?? property.ClrType).UnwrapNullableType(); - return type.IsInteger() - && (property.GetValueConverter() - ?? (property.FindRelationalTypeMapping(storeObject) - ?? typeMappingSource?.FindMapping((IProperty)property))?.Converter) - == null; + return type.IsInteger(); } #endregion Value generation diff --git a/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs b/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs index ec50268d7..744efa803 100644 --- a/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs +++ b/src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs @@ -242,7 +242,7 @@ public override DbContextOptionsExtensionInfo Info private sealed class ExtensionInfo : RelationalExtensionInfo { - private long? _serviceProviderHash; + private int? _serviceProviderHash; private string? _logFragment; public ExtensionInfo(IDbContextOptionsExtension extension) @@ -324,26 +324,29 @@ public override string LogFragment } } - public override long GetServiceProviderHashCode() + public override int GetServiceProviderHashCode() { - unchecked + if (_serviceProviderHash == null) { - if (_serviceProviderHash == null) + var hashCode = new HashCode(); + + foreach (var userRangeDefinition in Extension._userRangeDefinitions) { - _serviceProviderHash = Extension._userRangeDefinitions.Aggregate( - base.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); - _serviceProviderHash = (_serviceProviderHash * 397) ^ Extension.ReverseNullOrdering.GetHashCode(); + hashCode.Add(userRangeDefinition); } - return _serviceProviderHash.Value; + hashCode.Add(Extension.AdminDatabase); + hashCode.Add(Extension.PostgresVersion); + hashCode.Add(Extension.UseRedshift); + hashCode.Add(Extension.ProvideClientCertificatesCallback); + hashCode.Add(Extension.RemoteCertificateValidationCallback); + hashCode.Add(Extension.ProvidePasswordCallback); + hashCode.Add(Extension.ReverseNullOrdering); + + _serviceProviderHash = hashCode.ToHashCode(); } + + return _serviceProviderHash.Value; } /// diff --git a/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs b/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs index 9fe7eb754..8be9a60d6 100644 --- a/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs +++ b/src/EFCore.PG/Update/Internal/NpgsqlModificationCommandBatch.cs @@ -52,12 +52,12 @@ public NpgsqlModificationCommandBatch( protected override int GetParameterCount() => _parameterCount; - protected override bool CanAddCommand(ModificationCommand modificationCommand) + protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) { if (ModificationCommands.Count >= _maxBatchSize) return false; - var newParamCount = (long)_parameterCount + (long)modificationCommand.ColumnModifications.Count; + var newParamCount = (long)_parameterCount + modificationCommand.ColumnModifications.Count; if (newParamCount > int.MaxValue) return false; diff --git a/src/EFCore.PG/Update/Internal/NpgsqlUpdateSqlGenerator.cs b/src/EFCore.PG/Update/Internal/NpgsqlUpdateSqlGenerator.cs index 9c6af05a4..821b5dd80 100644 --- a/src/EFCore.PG/Update/Internal/NpgsqlUpdateSqlGenerator.cs +++ b/src/EFCore.PG/Update/Internal/NpgsqlUpdateSqlGenerator.cs @@ -16,13 +16,13 @@ public NpgsqlUpdateSqlGenerator(UpdateSqlGeneratorDependencies dependencies) public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, - ModificationCommand command, + IReadOnlyModificationCommand command, int commandPosition) => AppendInsertOperation(commandStringBuilder, command, commandPosition, false); public virtual ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, - ModificationCommand command, + IReadOnlyModificationCommand command, int commandPosition, bool overridingSystemValue) { @@ -51,7 +51,7 @@ public virtual ResultSetMapping AppendInsertOperation( public override ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, - ModificationCommand command, + IReadOnlyModificationCommand command, int commandPosition) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); @@ -78,7 +78,7 @@ public override ResultSetMapping AppendUpdateOperation( // ReSharper disable once ParameterTypeCanBeEnumerable.Local private void AppendReturningClause( StringBuilder commandStringBuilder, - IReadOnlyList operations) + IReadOnlyList operations) { commandStringBuilder .AppendLine() @@ -95,19 +95,16 @@ public override void AppendNextSequenceValueOperation(StringBuilder commandStrin public override void AppendBatchHeader(StringBuilder commandStringBuilder) { - Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); - - // TODO: Npgsql } - protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, ColumnModification columnModification) + protected override void AppendIdentityWhereCondition(StringBuilder commandStringBuilder, IColumnModification columnModification) { - throw new NotImplementedException(); + throw new NotSupportedException(); } protected override void AppendRowsAffectedWhereCondition(StringBuilder commandStringBuilder, int expectedRowsAffected) { - throw new NotImplementedException(); + throw new NotSupportedException(); } public enum ResultsGrouping diff --git a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs index 5b0d228f1..fb03dcec5 100644 --- a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs @@ -1491,6 +1491,35 @@ public override async Task Drop_column_primary_key() @"ALTER TABLE ""People"" DROP COLUMN ""Id"";"); } + [ConditionalFact] + public override async Task Drop_column_computed_and_non_computed_with_dependency() + { + if (TestEnvironment.PostgresVersion.IsUnder(12)) + { + return; + } + + await Test( + builder => builder.Entity("People").Property("Id"), + builder => builder.Entity( + "People", e => + { + e.Property("X"); + e.Property("Y").HasComputedColumnSql($"{DelimitIdentifier("X")} + 1", stored: true); + }), + builder => { }, + model => + { + var table = Assert.Single(model.Tables); + Assert.Equal("Id", Assert.Single(table.Columns).Name); + }); + + AssertSql( + @"ALTER TABLE ""People"" DROP COLUMN ""Y"";", + // + @"ALTER TABLE ""People"" DROP COLUMN ""X"";"); + } + [Fact] public virtual async Task Drop_column_system() { diff --git a/test/EFCore.PG.FunctionalTests/NpgsqlValueGenerationScenariosTest.cs b/test/EFCore.PG.FunctionalTests/NpgsqlValueGenerationScenariosTest.cs index 98f2525b9..6feccda34 100644 --- a/test/EFCore.PG.FunctionalTests/NpgsqlValueGenerationScenariosTest.cs +++ b/test/EFCore.PG.FunctionalTests/NpgsqlValueGenerationScenariosTest.cs @@ -3,6 +3,8 @@ using System.Linq; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.EntityFrameworkCore.ValueGeneration.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; using Xunit; @@ -150,6 +152,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasDefaultValue(); } + public class BlogWithStringKey + { + public string Id { get; set; } + public string Name { get; set; } + } + [Fact] public void Insert_with_key_default_value_from_sequence() { @@ -194,6 +202,105 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) } } + [ConditionalFact] + public void Insert_uint_to_Identity_column_using_value_converter() + { + using var testStore = NpgsqlTestStore.CreateInitialized(DatabaseName); + using (var context = new BlogContextUIntToIdentityUsingValueConverter(testStore.Name)) + { + context.Database.EnsureCreatedResiliently(); + + context.AddRange( + new BlogWithUIntKey { Name = "One Unicorn" }, new BlogWithUIntKey { Name = "Two Unicorns" }); + + context.SaveChanges(); + } + + using (var context = new BlogContextUIntToIdentityUsingValueConverter(testStore.Name)) + { + var blogs = context.UnsignedBlogs.OrderBy(e => e.Id).ToList(); + + Assert.Equal((uint)1, blogs[0].Id); + Assert.Equal((uint)2, blogs[1].Id); + } + } + + public class BlogContextUIntToIdentityUsingValueConverter : ContextBase + { + public BlogContextUIntToIdentityUsingValueConverter(string databaseName) + : base(databaseName) + { + } + + public DbSet UnsignedBlogs { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder + .Entity() + .Property(e => e.Id) + .HasConversion(); + } + } + + public class BlogWithUIntKey + { + public uint Id { get; set; } + public string Name { get; set; } + } + + [ConditionalFact] + public void Insert_string_to_Identity_column_using_value_converter() + { + using var testStore = NpgsqlTestStore.CreateInitialized(DatabaseName); + using (var context = new BlogContextStringToIdentityUsingValueConverter(testStore.Name)) + { + context.Database.EnsureCreatedResiliently(); + + context.AddRange( + new BlogWithStringKey { Name = "One Unicorn" }, new BlogWithStringKey { Name = "Two Unicorns" }); + + context.SaveChanges(); + } + + using (var context = new BlogContextStringToIdentityUsingValueConverter(testStore.Name)) + { + var blogs = context.StringyBlogs.OrderBy(e => e.Id).ToList(); + + Assert.Equal("1", blogs[0].Id); + Assert.Equal("2", blogs[1].Id); + } + } + + public class BlogContextStringToIdentityUsingValueConverter : ContextBase + { + public BlogContextStringToIdentityUsingValueConverter(string databaseName) + : base(databaseName) + { + } + + public DbSet StringyBlogs { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + Guid guid; + modelBuilder + .Entity() + .Property(e => e.Id) + .HasValueGenerator() + .HasConversion( + v => Guid.TryParse(v, out guid) + ? default + : int.Parse(v), + v => v.ToString()) + .ValueGeneratedOnAdd(); + } + } + [Fact] public void Insert_with_explicit_non_default_keys() { diff --git a/test/EFCore.PG.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs b/test/EFCore.PG.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs index dd382c323..9cd3fdf24 100644 --- a/test/EFCore.PG.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs +++ b/test/EFCore.PG.Tests/TestUtilities/FakeRelationalCommandDiagnosticsLogger.cs @@ -19,7 +19,8 @@ public InterceptionResult CommandCreating( DbContext? context, Guid commandId, Guid connectionId, - DateTimeOffset startTime) + DateTimeOffset startTime, + CommandSource commandSource) => default; public DbCommand CommandCreated( @@ -30,6 +31,7 @@ public DbCommand CommandCreated( Guid commandId, Guid connectionId, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration) => command; @@ -39,7 +41,8 @@ public InterceptionResult CommandReaderExecuting( DbContext? context, Guid commandId, Guid connectionId, - DateTimeOffset startTime) + DateTimeOffset startTime, + CommandSource commandSource) => default; public InterceptionResult CommandScalarExecuting( @@ -48,26 +51,18 @@ public InterceptionResult CommandScalarExecuting( DbContext? context, Guid commandId, Guid connectionId, - DateTimeOffset startTime) + DateTimeOffset startTime, + CommandSource commandSource) => default; - /// - /// Logs for the event. - /// - /// The connection. - /// The database command object. - /// The currently being used, to null if not known. - /// The correlation ID associated with the given . - /// The correlation ID associated with the being used. - /// The time that execution began. - /// An intercepted result. public InterceptionResult CommandNonQueryExecuting( IRelationalConnection connection, DbCommand command, DbContext? context, Guid commandId, Guid connectionId, - DateTimeOffset startTime) + DateTimeOffset startTime, + CommandSource commandSource) => default; public ValueTask> CommandReaderExecutingAsync( @@ -77,6 +72,7 @@ public ValueTask> CommandReaderExecutingAsync( Guid commandId, Guid connectionId, DateTimeOffset startTime, + CommandSource commandSource, CancellationToken cancellationToken = default) => default; @@ -87,6 +83,7 @@ public ValueTask> CommandScalarExecutingAsync( Guid commandId, Guid connectionId, DateTimeOffset startTime, + CommandSource commandSource, CancellationToken cancellationToken = default) => default; @@ -97,6 +94,7 @@ public ValueTask> CommandNonQueryExecutingAsync( Guid commandId, Guid connectionId, DateTimeOffset startTime, + CommandSource commandSource, CancellationToken cancellationToken = default) => default; @@ -108,6 +106,7 @@ public DbDataReader CommandReaderExecuted( Guid connectionId, DbDataReader methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration) => methodResult; @@ -119,6 +118,7 @@ public DbDataReader CommandReaderExecuted( Guid connectionId, object? methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration) => methodResult; @@ -130,6 +130,7 @@ public int CommandNonQueryExecuted( Guid connectionId, int methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration) => methodResult; @@ -141,6 +142,7 @@ public ValueTask CommandReaderExecutedAsync( Guid connectionId, DbDataReader methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration, CancellationToken cancellationToken = default) => new(methodResult); @@ -153,6 +155,7 @@ public ValueTask CommandReaderExecutedAsync( Guid connectionId, object? methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration, CancellationToken cancellationToken = default) => new(methodResult); @@ -165,6 +168,7 @@ public ValueTask CommandNonQueryExecutedAsync( Guid connectionId, int methodResult, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration, CancellationToken cancellationToken = default) => new(methodResult); @@ -178,6 +182,7 @@ public void CommandError( Guid connectionId, Exception exception, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration) { } @@ -191,6 +196,7 @@ public Task CommandErrorAsync( Guid connectionId, Exception exception, DateTimeOffset startTime, + CommandSource commandSource, TimeSpan duration, CancellationToken cancellationToken = default) => Task.CompletedTask; diff --git a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs index f38c26e86..6f3a2c1fb 100644 --- a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs +++ b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.EntityFrameworkCore.Update; +using Microsoft.EntityFrameworkCore.Update.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; @@ -49,8 +50,8 @@ public void Uses_MaxBatchSize_specified_in_NpgsqlOptionsExtension() var batch = factory.Create(); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); - Assert.False(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + Assert.True(batch.AddCommand(CreateModificationCommand("T1", null, false))); + Assert.False(batch.AddCommand(CreateModificationCommand("T1", null, false))); } [Fact] @@ -88,12 +89,26 @@ public void MaxBatchSize_is_optional() var batch = factory.Create(); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + Assert.True(batch.AddCommand(CreateModificationCommand("T1", null, false))); + Assert.True(batch.AddCommand(CreateModificationCommand("T1", null, false))); } private class FakeDbContext : DbContext { } + + private static IModificationCommand CreateModificationCommand( + string name, + string schema, + bool sensitiveLoggingEnabled) + { + var modificationCommandParameters = new ModificationCommandParameters( + name, schema, sensitiveLoggingEnabled); + + var modificationCommand = new ModificationCommandFactory().CreateModificationCommand( + modificationCommandParameters); + + return modificationCommand; + } } } diff --git a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs index e25141c88..0c46167df 100644 --- a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs +++ b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.EntityFrameworkCore.Update; +using Microsoft.EntityFrameworkCore.Update.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal; using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities; @@ -50,14 +51,28 @@ public void AddCommand_returns_false_when_max_batch_size_is_reached() Assert.True( batch.AddCommand( - new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + CreateModificationCommand("T1", null, false))); Assert.False( batch.AddCommand( - new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + CreateModificationCommand("T1", null, false))); } private class FakeDbContext : DbContext { } + + private static IModificationCommand CreateModificationCommand( + string name, + string schema, + bool sensitiveLoggingEnabled) + { + var modificationCommandParameters = new ModificationCommandParameters( + name, schema, sensitiveLoggingEnabled); + + var modificationCommand = new ModificationCommandFactory().CreateModificationCommand( + modificationCommandParameters); + + return modificationCommand; + } } }