From 559cdc6d3c1bd4a6358a925c1344ceb21e5c4794 Mon Sep 17 00:00:00 2001 From: Christopher Jolly Date: Wed, 1 Nov 2023 01:15:06 +0800 Subject: [PATCH] Some updates to the migration/update sql. Main change is if we are doing an INSERT, if there is no values to be read back we don't have to follow it up with a 'SELECT @@ROWCOUNT' --- .../Migrations/JetMigrationsSqlGenerator.cs | 45 +++- .../Internal/JetModificationCommandBatch.cs | 62 ++--- .../Update/Internal/JetUpdateSqlGenerator.cs | 12 + .../EntitySplittingSqlServerTest.cs | 1 - .../JetDatabaseCreatorTest.cs | 14 +- .../JetMigrationsSqlGeneratorTest.cs | 219 +++++++++--------- .../TPTTableSplittingJetTest.cs | 1 - .../Update/JetUpdateSqlGeneratorTest.cs | 6 - test/EFCore.Jet.Tests/JetMigrationTest.cs | 52 ++--- 9 files changed, 221 insertions(+), 191 deletions(-) diff --git a/src/EFCore.Jet/Migrations/JetMigrationsSqlGenerator.cs b/src/EFCore.Jet/Migrations/JetMigrationsSqlGenerator.cs index 746eeda..fc13c83 100644 --- a/src/EFCore.Jet/Migrations/JetMigrationsSqlGenerator.cs +++ b/src/EFCore.Jet/Migrations/JetMigrationsSqlGenerator.cs @@ -16,6 +16,9 @@ using Microsoft.EntityFrameworkCore.Migrations.Operations; using Microsoft.EntityFrameworkCore.Storage; using EntityFrameworkCore.Jet.Utilities; using Microsoft.Extensions.DependencyInjection; +using System.Text; +using EntityFrameworkCore.Jet.Update.Internal; +using Microsoft.EntityFrameworkCore.Update; // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore.Migrations @@ -38,22 +41,25 @@ namespace Microsoft.EntityFrameworkCore.Migrations private IReadOnlyList _operations = null!; private RelationalTypeMapping _stringTypeMapping; - + private readonly ICommandBatchPreparer _commandBatchPreparer; /// /// Creates a new instance. /// /// Parameter object containing dependencies for this service. /// Provider-specific Migrations annotations to use. /// Provider-specific options. + /// The command batch preparer. public JetMigrationsSqlGenerator( [NotNull] MigrationsSqlGeneratorDependencies dependencies, [NotNull] IMigrationsAnnotationProvider migrationsAnnotations, - [NotNull] IJetOptions options) + [NotNull] IJetOptions options, + ICommandBatchPreparer commandBatchPreparer) : base(dependencies) { _migrationsAnnotations = migrationsAnnotations; _options = options; _stringTypeMapping = dependencies.TypeMappingSource.FindMapping(typeof(string))!; + _commandBatchPreparer = commandBatchPreparer; } /// @@ -704,6 +710,41 @@ namespace Microsoft.EntityFrameworkCore.Migrations } } + protected override void Generate( + InsertDataOperation operation, + IModel? model, + MigrationCommandListBuilder builder, + bool terminate = true) + { + var sqlBuilder = new StringBuilder(); + + var modificationCommands = GenerateModificationCommands(operation, model).ToList(); + var updateSqlGenerator = (IJetUpdateSqlGenerator)Dependencies.UpdateSqlGenerator; + + foreach (var batch in _commandBatchPreparer.CreateCommandBatches(modificationCommands, moreCommandSets: true)) + { + updateSqlGenerator.AppendBulkInsertOperation(sqlBuilder, batch.ModificationCommands, commandPosition: 0); + } + + if (Options.HasFlag(MigrationsSqlGenerationOptions.Idempotent)) + { + builder + .Append("EXEC('") + .Append(sqlBuilder.ToString().TrimEnd('\n', '\r', ';').Replace("'", "''")) + .Append("')") + .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); + } + else + { + builder.Append(sqlBuilder.ToString()); + } + + if (terminate) + { + builder.EndCommand(); + } + } + protected override void ColumnDefinition( string? schema, string table, diff --git a/src/EFCore.Jet/Update/Internal/JetModificationCommandBatch.cs b/src/EFCore.Jet/Update/Internal/JetModificationCommandBatch.cs index 3bd0e80..f811d9f 100644 --- a/src/EFCore.Jet/Update/Internal/JetModificationCommandBatch.cs +++ b/src/EFCore.Jet/Update/Internal/JetModificationCommandBatch.cs @@ -30,7 +30,7 @@ namespace EntityFrameworkCore.Jet.Update.Internal /// public JetModificationCommandBatch( [NotNull] ModificationCommandBatchFactoryDependencies dependencies) - : base(dependencies,1) + : base(dependencies, 1) { // See https://support.office.com/en-us/article/access-specifications-0cf3c66f-9cf2-4e32-9568-98c1025bb47c // for Access specifications and limits. @@ -93,9 +93,11 @@ namespace EntityFrameworkCore.Jet.Update.Internal ResultSetMappings.Add(resultSetMapping); } - if (resultSetMapping != ResultSetMapping.NoResults) + // All result mappings are marked as "not last", mark the last one as "last". + if (resultSetMapping.HasFlag(ResultSetMapping.HasResultRow)) { - ResultSetMappings[^1] = ResultSetMapping.LastInResultSet; + ResultSetMappings[^1] &= ~ResultSetMapping.NotLastInResultSet; + ResultSetMappings[^1] |= ResultSetMapping.LastInResultSet; } } @@ -105,33 +107,39 @@ namespace EntityFrameworkCore.Jet.Update.Internal /// 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. /// - protected override void AddCommand(IReadOnlyModificationCommand modificationCommand) + public override bool TryAddCommand(IReadOnlyModificationCommand modificationCommand) { - if (modificationCommand.EntityState == EntityState.Added && modificationCommand.StoreStoredProcedure is null) + // If there are any pending bulk insert commands and the new command is incompatible with them (not an insert, insert into a + // separate table..), apply the pending commands. + if (_pendingBulkInsertCommands.Count > 0 + && (modificationCommand.EntityState != EntityState.Added + || modificationCommand.StoreStoredProcedure is not null + || !CanBeInsertedInSameStatement(_pendingBulkInsertCommands[0], modificationCommand))) { - if (_pendingBulkInsertCommands.Count > 0 - && !CanBeInsertedInSameStatement(_pendingBulkInsertCommands[0], modificationCommand)) - { - // The new Add command cannot be added to the pending bulk insert commands (e.g. different table). - // Write out the pending commands before starting a new pending chain. - ApplyPendingBulkInsertCommands(); - _pendingBulkInsertCommands.Clear(); - } + ApplyPendingBulkInsertCommands(); + _pendingBulkInsertCommands.Clear(); + } + + return base.TryAddCommand(modificationCommand); + } + /// + /// 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. + /// + protected override void AddCommand(IReadOnlyModificationCommand modificationCommand) + { + // TryAddCommand above already applied any pending commands if the new command is incompatible with them. + // So if the new command is an insert, just append it to pending, otherwise do the regular add logic. + if (modificationCommand is { EntityState: EntityState.Added, StoreStoredProcedure: null }) + { _pendingBulkInsertCommands.Add(modificationCommand); AddParameters(modificationCommand); } else { - // If we have any pending bulk insert commands, write them out before the next non-Add command - if (_pendingBulkInsertCommands.Count > 0) - { - // Note that we don't care about the transactionality of the bulk insert SQL, since there's the additional non-Add - // command coming right afterwards, and so a transaction is required in any case. - ApplyPendingBulkInsertCommands(); - _pendingBulkInsertCommands.Clear(); - } - base.AddCommand(modificationCommand); } } @@ -140,11 +148,11 @@ namespace EntityFrameworkCore.Jet.Update.Internal IReadOnlyModificationCommand firstCommand, IReadOnlyModificationCommand secondCommand) => firstCommand.TableName == secondCommand.TableName - && firstCommand.Schema == secondCommand.Schema - && firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual( - secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)) - && firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual( - secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName)); + && firstCommand.Schema == secondCommand.Schema + && firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual( + secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)) + && firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual( + secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName)); /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Jet/Update/Internal/JetUpdateSqlGenerator.cs b/src/EFCore.Jet/Update/Internal/JetUpdateSqlGenerator.cs index 862d975..7daf389 100644 --- a/src/EFCore.Jet/Update/Internal/JetUpdateSqlGenerator.cs +++ b/src/EFCore.Jet/Update/Internal/JetUpdateSqlGenerator.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Text; using EntityFrameworkCore.Jet.Metadata; +using EntityFrameworkCore.Jet.Utilities; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; @@ -34,6 +35,17 @@ namespace EntityFrameworkCore.Jet.Update.Internal { } + public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, + int commandPosition, out bool requiresTransaction) + { + //No database columns need to be read back + if (command.ColumnModifications.All(o => !o.IsRead)) + { + return AppendInsertReturningOperation(commandStringBuilder, command, commandPosition, out requiresTransaction); + } + return base.AppendInsertOperation(commandStringBuilder, command, commandPosition, out requiresTransaction); + } + public ResultSetMapping AppendBulkInsertOperation(StringBuilder commandStringBuilder, IReadOnlyList modificationCommands, int commandPosition, out bool requiresTransaction) { var firstCommand = modificationCommands[0]; diff --git a/test/EFCore.Jet.FunctionalTests/EntitySplittingSqlServerTest.cs b/test/EFCore.Jet.FunctionalTests/EntitySplittingSqlServerTest.cs index 567fc65..f24a8b1 100644 --- a/test/EFCore.Jet.FunctionalTests/EntitySplittingSqlServerTest.cs +++ b/test/EFCore.Jet.FunctionalTests/EntitySplittingSqlServerTest.cs @@ -95,7 +95,6 @@ WHERE @@ROWCOUNT = 1 AND `Id` = @@identity; INSERT INTO `MeterReadingDetails` (`Id`, `CurrentRead`, `PreviousRead`) VALUES (@p1, @p2, @p3); -SELECT @@ROWCOUNT; """, // """ diff --git a/test/EFCore.Jet.FunctionalTests/JetDatabaseCreatorTest.cs b/test/EFCore.Jet.FunctionalTests/JetDatabaseCreatorTest.cs index 02708bb..eedd444 100644 --- a/test/EFCore.Jet.FunctionalTests/JetDatabaseCreatorTest.cs +++ b/test/EFCore.Jet.FunctionalTests/JetDatabaseCreatorTest.cs @@ -643,26 +643,24 @@ namespace EntityFrameworkCore.Jet.FunctionalTests + _eol + " `NotFigTime` datetime NOT NULL," + _eol - + " `ToEat` tinyint NOT NULL," + + " `ToEat` byte NOT NULL," + _eol - + " `OrNothing` float NOT NULL," + + " `OrNothing` double NOT NULL," + _eol + " `Fuse` smallint NOT NULL," + _eol - + " `WayRound` bigint NOT NULL," + + " `WayRound` decimal(20,0) NOT NULL," + _eol - + " `On` real NOT NULL," + + " `On` single NOT NULL," + _eol - + " `AndChew` varbinary(max) NULL," + + " `AndChew` longbinary NULL," + _eol - + " `AndRow` rowversion NULL," + + " `AndRow` varbinary(8) NULL," + _eol + " CONSTRAINT `PK_Blogs` PRIMARY KEY (`Key1`, `Key2`)" + _eol + ");" + _eol - + "GO" - + _eol + _eol + _eol, script); diff --git a/test/EFCore.Jet.FunctionalTests/JetMigrationsSqlGeneratorTest.cs b/test/EFCore.Jet.FunctionalTests/JetMigrationsSqlGeneratorTest.cs index c4ee3a6..33e5d29 100644 --- a/test/EFCore.Jet.FunctionalTests/JetMigrationsSqlGeneratorTest.cs +++ b/test/EFCore.Jet.FunctionalTests/JetMigrationsSqlGeneratorTest.cs @@ -312,7 +312,7 @@ CREATE INDEX `IX_Person_Name` ON `Person` (`Name`); AssertSql( @"ALTER TABLE `Person` ALTER COLUMN `Id` DROP DEFAULT; -ALTER TABLE `Person` ALTER COLUMN `Id` integer NOT NULL; +ALTER TABLE `Person` ALTER COLUMN `Id` decimal(20,0) NOT NULL; "); } @@ -366,97 +366,97 @@ ALTER TABLE `Person` ALTER COLUMN `Id` integer NOT NULL; "); } -// [ConditionalFact] -// public virtual void CreateDatabaseOperation_with_filename() -// { -// Generate( -// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "Narf.mdf" }); -// -// var expectedFile = Path.GetFullPath("Narf.mdf"); -// var expectedLog = Path.GetFullPath("Narf_log.ldf"); -// -// AssertSql( -// $@"CREATE DATABASE [Northwind] -// ON (NAME = 'Narf', FILENAME = '{expectedFile}') -// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); -// GO -// -// IF SERVERPROPERTY('EngineEdition') <> 5 -// BEGIN -// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; -// END; -// "); -// } - -// [ConditionalFact] -// public virtual void CreateDatabaseOperation_with_filename_and_datadirectory() -// { -// var baseDirectory = AppDomain.CurrentDomain.BaseDirectory; -// -// Generate( -// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" }); -// -// var expectedFile = Path.Combine(baseDirectory, "Narf.mdf"); -// var expectedLog = Path.Combine(baseDirectory, "Narf_log.ldf"); -// -// AssertSql( -// $@"CREATE DATABASE [Northwind] -// ON (NAME = 'Narf', FILENAME = '{expectedFile}') -// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); -// GO -// -// IF SERVERPROPERTY('EngineEdition') <> 5 -// BEGIN -// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; -// END; -// "); -// } - -// [ConditionalFact] -// public virtual void CreateDatabaseOperation_with_filename_and_custom_datadirectory() -// { -// var dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data"); -// -// AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory); -// -// Generate( -// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" }); -// -// AppDomain.CurrentDomain.SetData("DataDirectory", null); -// -// var expectedFile = Path.Combine(dataDirectory, "Narf.mdf"); -// var expectedLog = Path.Combine(dataDirectory, "Narf_log.ldf"); -// -// AssertSql( -// $@"CREATE DATABASE [Northwind] -// ON (NAME = 'Narf', FILENAME = '{expectedFile}') -// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); -// GO -// -// IF SERVERPROPERTY('EngineEdition') <> 5 -// BEGIN -// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; -// END; -// "); -// } - -// [ConditionalFact] -// public virtual void CreateDatabaseOperation_with_collation() -// { -// Generate( -// new JetCreateDatabaseOperation { Name = "Northwind", Collation = "German_PhoneBook_CI_AS" }); -// -// AssertSql( -// @"CREATE DATABASE [Northwind] -// COLLATE German_PhoneBook_CI_AS; -// GO -// -// IF SERVERPROPERTY('EngineEdition') <> 5 -// BEGIN -// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; -// END; -// "); -// } + // [ConditionalFact] + // public virtual void CreateDatabaseOperation_with_filename() + // { + // Generate( + // new JetCreateDatabaseOperation { Name = "Northwind", FileName = "Narf.mdf" }); + // + // var expectedFile = Path.GetFullPath("Narf.mdf"); + // var expectedLog = Path.GetFullPath("Narf_log.ldf"); + // + // AssertSql( + // $@"CREATE DATABASE [Northwind] + // ON (NAME = 'Narf', FILENAME = '{expectedFile}') + // LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); + // GO + // + // IF SERVERPROPERTY('EngineEdition') <> 5 + // BEGIN + // ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; + // END; + // "); + // } + + // [ConditionalFact] + // public virtual void CreateDatabaseOperation_with_filename_and_datadirectory() + // { + // var baseDirectory = AppDomain.CurrentDomain.BaseDirectory; + // + // Generate( + // new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" }); + // + // var expectedFile = Path.Combine(baseDirectory, "Narf.mdf"); + // var expectedLog = Path.Combine(baseDirectory, "Narf_log.ldf"); + // + // AssertSql( + // $@"CREATE DATABASE [Northwind] + // ON (NAME = 'Narf', FILENAME = '{expectedFile}') + // LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); + // GO + // + // IF SERVERPROPERTY('EngineEdition') <> 5 + // BEGIN + // ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; + // END; + // "); + // } + + // [ConditionalFact] + // public virtual void CreateDatabaseOperation_with_filename_and_custom_datadirectory() + // { + // var dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data"); + // + // AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory); + // + // Generate( + // new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" }); + // + // AppDomain.CurrentDomain.SetData("DataDirectory", null); + // + // var expectedFile = Path.Combine(dataDirectory, "Narf.mdf"); + // var expectedLog = Path.Combine(dataDirectory, "Narf_log.ldf"); + // + // AssertSql( + // $@"CREATE DATABASE [Northwind] + // ON (NAME = 'Narf', FILENAME = '{expectedFile}') + // LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}'); + // GO + // + // IF SERVERPROPERTY('EngineEdition') <> 5 + // BEGIN + // ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; + // END; + // "); + // } + + // [ConditionalFact] + // public virtual void CreateDatabaseOperation_with_collation() + // { + // Generate( + // new JetCreateDatabaseOperation { Name = "Northwind", Collation = "German_PhoneBook_CI_AS" }); + // + // AssertSql( + // @"CREATE DATABASE [Northwind] + // COLLATE German_PhoneBook_CI_AS; + // GO + // + // IF SERVERPROPERTY('EngineEdition') <> 5 + // BEGIN + // ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON; + // END; + // "); + // } [ConditionalFact] public virtual void AlterDatabaseOperation_collation() @@ -694,8 +694,9 @@ VALUES ('John', 'Snow'); AssertSql( @"INSERT INTO `People` (`First Name`) -VALUES ('John'), -('Daenerys'); +VALUES ('John'); +INSERT INTO `People` (`First Name`) +VALUES ('Daenerys'); "); } @@ -976,30 +977,18 @@ SELECT @@ROWCOUNT; MigrationsSqlGenerationOptions.Idempotent); AssertSql( - @"CREATE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WHERE [Column1] IS NOT NULL; + @"CREATE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WITH [Column1] IS NOT NULL; "); } - - [ConditionalFact] - public virtual void CreateIndex_generates_exec_when_legacy_filter_and_idempotent() + [ConditionalTheory(Skip = "No sequences")] + public override void Sequence_restart_operation(long? startsAt) { - Generate( - modelBuilder => - { - modelBuilder - .HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0") - .Entity("Table1").Property("Column1"); - }, - migrationBuilder => migrationBuilder.CreateIndex( - name: "IX_Table1_Column1", - table: "Table1", - column: "Column1", - unique: true), - MigrationsSqlGenerationOptions.Idempotent); + base.Sequence_restart_operation(startsAt); - AssertSql( - @"CREATE UNIQUE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WHERE `Column1` IS NOT NULL'; -"); + var expectedSql = startsAt.HasValue + ? @$"ALTER SEQUENCE [dbo].[TestRestartSequenceOperation] RESTART WITH {startsAt};" + : @"ALTER SEQUENCE [dbo].[TestRestartSequenceOperation] RESTART;"; + AssertSql(expectedSql); } [ConditionalFact] @@ -1021,7 +1010,7 @@ SELECT @@ROWCOUNT; $@"ALTER TABLE `People` ADD `Birthday` datetime NOT NULL DEFAULT #2019-01-01#; "); } - + public JetMigrationsSqlGeneratorTest() : base( JetTestHelpers.Instance, diff --git a/test/EFCore.Jet.FunctionalTests/TPTTableSplittingJetTest.cs b/test/EFCore.Jet.FunctionalTests/TPTTableSplittingJetTest.cs index bfdf651..3793454 100644 --- a/test/EFCore.Jet.FunctionalTests/TPTTableSplittingJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/TPTTableSplittingJetTest.cs @@ -159,7 +159,6 @@ WHERE ([c].[Capacity] IS NOT NULL) AND ([c].[FuelType] IS NOT NULL) INSERT INTO `LicensedOperators` (`VehicleName`, `LicenseType`) VALUES (@p0, @p1); -SELECT @@ROWCOUNT; """ , """ diff --git a/test/EFCore.Jet.FunctionalTests/Update/JetUpdateSqlGeneratorTest.cs b/test/EFCore.Jet.FunctionalTests/Update/JetUpdateSqlGeneratorTest.cs index 2c0bc38..44bbf72 100644 --- a/test/EFCore.Jet.FunctionalTests/Update/JetUpdateSqlGeneratorTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Update/JetUpdateSqlGeneratorTest.cs @@ -132,11 +132,8 @@ OUTPUT INSERTED.[Id], INSERTED.[Computed], i._Position; """ INSERT INTO `Ducks` (`Id`, `Name`, `Quacks`, `ConcurrencyToken`) VALUES (@p0, @p1, @p2, @p3); -SELECT @@ROWCOUNT; - INSERT INTO `Ducks` (`Id`, `Name`, `Quacks`, `ConcurrencyToken`) VALUES (@p0, @p1, @p2, @p3); -SELECT @@ROWCOUNT; """, stringBuilder.ToString()); Assert.Equal(ResultSetMapping.NoResults, grouping); @@ -179,11 +176,8 @@ INNER JOIN @inserted0 i ON ([t].[Id] = [i].[Id]); """ INSERT INTO `Ducks` DEFAULT VALUES; -SELECT @@ROWCOUNT; - INSERT INTO `Ducks` DEFAULT VALUES; -SELECT @@ROWCOUNT; """; AssertBaseline(expectedText, stringBuilder.ToString()); Assert.Equal(ResultSetMapping.NoResults, grouping); diff --git a/test/EFCore.Jet.Tests/JetMigrationTest.cs b/test/EFCore.Jet.Tests/JetMigrationTest.cs index 66c39a8..6174b60 100644 --- a/test/EFCore.Jet.Tests/JetMigrationTest.cs +++ b/test/EFCore.Jet.Tests/JetMigrationTest.cs @@ -27,13 +27,13 @@ namespace EntityFrameworkCore.Jet }); }); }); - + var cookies = context.Set() .ToList(); - + Assert.Single(cookies); Assert.Equal(new DateTime(2021, 12, 31), cookies[0].BestServedBefore); - + AssertSql( $@"CREATE TABLE `Cookie` ( `CookieId` counter NOT NULL, @@ -44,7 +44,6 @@ namespace EntityFrameworkCore.Jet INSERT INTO `Cookie` (`CookieId`, `Name`) VALUES (1, 'Basic'); -SELECT @@ROWCOUNT; SELECT `c`.`CookieId`, `c`.`BestServedBefore`, `c`.`Name` FROM `Cookie` AS `c`"); @@ -60,7 +59,7 @@ FROM `Cookie` AS `c`"); { entity.Property(e => e.CookieId) .HasColumnType("counter"); - + entity.HasData( new Cookie { CookieId = 1, Name = "Chocolate Chip" }); }); @@ -69,11 +68,11 @@ FROM `Cookie` AS `c`"); { entity.Property(e => e.BackeryId) .HasColumnType("counter"); - + entity.HasData( new Backery { BackeryId = 1, Name = "Bread & Cookies" }); }); - + builder.Entity(entity => { entity.HasKey(e => new { e.CookieId, e.BackeryId }); @@ -85,17 +84,17 @@ FROM `Cookie` AS `c`"); entity.HasOne(d => d.Backery) .WithMany() .HasForeignKey(d => d.BackeryId); - + entity.HasData( new CookieBackery { CookieId = 1, BackeryId = 1 }); }); }); - + var cookieBackeries = context.Set() .Include(cb => cb.Cookie) .Include(cb => cb.Backery) .ToList(); - + Assert.Single(cookieBackeries); Assert.Equal(1, cookieBackeries[0].Cookie.CookieId); Assert.Equal(1, cookieBackeries[0].Backery.BackeryId); @@ -124,15 +123,12 @@ CREATE TABLE `CookieBackery` ( INSERT INTO `Backery` (`BackeryId`, `Name`) VALUES (1, 'Bread & Cookies'); -SELECT @@ROWCOUNT; INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`) VALUES (1, #1899-12-30#, 'Chocolate Chip'); -SELECT @@ROWCOUNT; INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`) VALUES (1, 1); -SELECT @@ROWCOUNT; CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`); @@ -152,7 +148,7 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); { entity.Property(e => e.CookieId) .HasColumnType("int"); - + entity.HasData( new Cookie { CookieId = 1, Name = "Chocolate Chip" }); }); @@ -161,11 +157,11 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); { entity.Property(e => e.BackeryId) .HasColumnType("int"); - + entity.HasData( new Backery { BackeryId = 1, Name = "Bread & Cookies" }); }); - + builder.Entity(entity => { entity.HasKey(e => new { e.CookieId, e.BackeryId }); @@ -177,17 +173,17 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); entity.HasOne(d => d.Backery) .WithMany() .HasForeignKey(d => d.BackeryId); - + entity.HasData( new CookieBackery { CookieId = 1, BackeryId = 1 }); }); }); - + var cookieBackeries = context.Set() .Include(cb => cb.Cookie) .Include(cb => cb.Backery) .ToList(); - + Assert.Single(cookieBackeries); Assert.Equal(1, cookieBackeries[0].Cookie.CookieId); Assert.Equal(1, cookieBackeries[0].Backery.BackeryId); @@ -216,15 +212,12 @@ CREATE TABLE `CookieBackery` ( INSERT INTO `Backery` (`BackeryId`, `Name`) VALUES (1, 'Bread & Cookies'); -SELECT @@ROWCOUNT; INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`) VALUES (1, #1899-12-30#, 'Chocolate Chip'); -SELECT @@ROWCOUNT; INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`) VALUES (1, 1); -SELECT @@ROWCOUNT; CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`); @@ -244,7 +237,7 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); { entity.Property(e => e.CookieId) .HasColumnType("int"); - + entity.HasData( new Cookie { CookieId = 1, Name = "Chocolate Chip" }); }); @@ -253,11 +246,11 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); { entity.Property(e => e.BackeryId) .HasColumnType("int"); - + entity.HasData( new Backery { BackeryId = 1, Name = "Bread & Cookies" }); }); - + builder.Entity(entity => { entity.HasKey(e => new { e.CookieId, e.BackeryId }); @@ -275,17 +268,17 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`"); entity.HasOne(d => d.Backery) .WithMany() .HasForeignKey(d => d.BackeryId); - + entity.HasData( new CookieBackery { CookieId = 1, BackeryId = 1 }); }); }); - + var cookieBackeries = context.Set() .Include(cb => cb.Cookie) .Include(cb => cb.Backery) .ToList(); - + Assert.Single(cookieBackeries); Assert.Equal(1, cookieBackeries[0].Cookie.CookieId); Assert.Equal(1, cookieBackeries[0].Backery.BackeryId); @@ -314,15 +307,12 @@ CREATE TABLE `CookieBackery` ( INSERT INTO `Backery` (`BackeryId`, `Name`) VALUES (1, 'Bread & Cookies'); -SELECT @@ROWCOUNT; INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`) VALUES (1, #1899-12-30#, 'Chocolate Chip'); -SELECT @@ROWCOUNT; INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`) VALUES (1, 1); -SELECT @@ROWCOUNT; CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`);