From b4eb7d71b003ac8246da3589bfc5de0dfced891c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 19 Sep 2022 10:38:21 +0200 Subject: [PATCH] Sproc test fixes around concurrency tokens Closes #29135 --- .../Update/StoredProcedureUpdateTestBase.cs | 50 +++++++++++++------ .../StoredProcedureUpdateSqlServerTest.cs | 10 ++-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs b/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs index 6a7abce9896..ddac87ace54 100644 --- a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs @@ -404,17 +404,26 @@ public virtual async Task Store_generated_concurrency_token_as_in_out_parameter( await using (var context2 = CreateContext()) { var entity2 = await context2.WithStoreGeneratedConcurrencyTokenAsInOutParameter.SingleAsync(w => w.Name == "Initial"); - entity2.Name = "Preempted"; - await SaveChanges(context2, async); - } + entity2.Name = "Updated"; - ClearLog(); + entity1.Name = "Preempted"; + await SaveChanges(context1, async); - entity1.Name = "Updated"; + ClearLog(); - var exception = await Assert.ThrowsAsync(async () => await SaveChanges(context1, async)); - var entry = exception.Entries.Single(); - Assert.Same(entity1, entry.Entity); + var exception = await Assert.ThrowsAsync(async () => await SaveChanges(context2, async)); + var entry = exception.Entries.Single(); + Assert.Same(entity2, entry.Entity); + } + + // Make sure we propagated the new concurrency token in the update above + using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents()) + { + entity1.Name = "Another update"; + await SaveChanges(context1, async); + + Assert.Equal("Another update", (await context1.WithStoreGeneratedConcurrencyTokenAsInOutParameter.SingleAsync(w => w.Id == entity1.Id)).Name); + } } [ConditionalTheory] @@ -430,17 +439,26 @@ public virtual async Task Store_generated_concurrency_token_as_two_parameters(bo await using (var context2 = CreateContext()) { var entity2 = await context2.WithStoreGeneratedConcurrencyTokenAsTwoParameters.SingleAsync(w => w.Name == "Initial"); - entity2.Name = "Preempted"; - await SaveChanges(context2, async); - } + entity2.Name = "Updated"; - ClearLog(); + entity1.Name = "Preempted"; + await SaveChanges(context1, async); - entity1.Name = "Updated"; + ClearLog(); - var exception = await Assert.ThrowsAsync(async () => await SaveChanges(context1, async)); - var entry = exception.Entries.Single(); - Assert.Same(entity1, entry.Entity); + var exception = await Assert.ThrowsAsync(async () => await SaveChanges(context2, async)); + var entry = exception.Entries.Single(); + Assert.Same(entity2, entry.Entity); + } + + // Make sure we propagated the new concurrency token in the update above + using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents()) + { + entity1.Name = "Another update"; + await SaveChanges(context1, async); + + Assert.Equal("Another update", (await context1.WithStoreGeneratedConcurrencyTokenAsTwoParameters.SingleAsync(w => w.Id == entity1.Id)).Name); + } } [ConditionalTheory] diff --git a/test/EFCore.SqlServer.FunctionalTests/Update/StoredProcedureUpdateSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Update/StoredProcedureUpdateSqlServerTest.cs index 4a67e71ef99..203b161dc3b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Update/StoredProcedureUpdateSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Update/StoredProcedureUpdateSqlServerTest.cs @@ -260,13 +260,11 @@ public override async Task Store_generated_concurrency_token_as_two_parameters(b // Can't assert SQL baseline as usual because the concurrency token changes Assert.Equal( - @"@p2='Updated' (Size = 4000) -@p3=NULL (Size = 8) (Direction = Output) (DbType = Binary) -@p4='0' (Direction = Output) + @"@p4='0' (Direction = Output) SET NOCOUNT ON; EXEC [WithStoreGeneratedConcurrencyTokenAsTwoParameters_Update] @p0, @p1, @p2, @p3 OUTPUT, @p4 OUTPUT;", - Fixture.TestSqlLoggerFactory.Sql.Substring(Fixture.TestSqlLoggerFactory.Sql.IndexOf("@p2", StringComparison.Ordinal)), + Fixture.TestSqlLoggerFactory.Sql.Substring(Fixture.TestSqlLoggerFactory.Sql.IndexOf("@p4", StringComparison.Ordinal)), ignoreLineEndingDifferences: true); } @@ -528,14 +526,16 @@ CREATE PROCEDURE WithStoreGeneratedConcurrencyTokenAsInOutParameter_Update(@Id i AS BEGIN UPDATE [WithStoreGeneratedConcurrencyTokenAsInOutParameter] SET [Name] = @Name WHERE [Id] = @Id AND [ConcurrencyToken] = @ConcurrencyToken; SET @RowsAffected = @@ROWCOUNT; + SELECT @ConcurrencyToken = [ConcurrencyToken] FROM [WithStoreGeneratedConcurrencyTokenAsInOutParameter] WHERE [Id] = @Id; END; GO CREATE PROCEDURE WithStoreGeneratedConcurrencyTokenAsTwoParameters_Update(@Id int, @ConcurrencyTokenIn rowversion, @Name varchar(max), @ConcurrencyTokenOut rowversion OUT, @RowsAffected int OUT) AS BEGIN - UPDATE [WithStoreGeneratedConcurrencyTokenAsTwoParameters] SET [Name] = @Name, @ConcurrencyTokenOut = [ConcurrencyToken] WHERE [Id] = @Id AND [ConcurrencyToken] = @ConcurrencyTokenIn; + UPDATE [WithStoreGeneratedConcurrencyTokenAsTwoParameters] SET [Name] = @Name WHERE [Id] = @Id AND [ConcurrencyToken] = @ConcurrencyTokenIn; SET @RowsAffected = @@ROWCOUNT; + SELECT @ConcurrencyTokenOut = [ConcurrencyToken] FROM [WithStoreGeneratedConcurrencyTokenAsTwoParameters] WHERE [Id] = @Id; END; GO