diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index d964d5ceeb2..b6beb5ada16 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -2,7 +2,7 @@
- $(NoWarn);CA1707;1591;xUnit1000;xUnit1003;xUnit1004;xUnit1010;xUnit1013;xUnit1026;xUnit2013
+ $(NoWarn);CA1707;1591;xUnit1000;xUnit1003;xUnit1004;xUnit1010;xUnit1013;xUnit1026;xUnit2013;xUnit1024
$(MSBuildThisFileDirectory)..\rulesets\EFCore.test.ruleset
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/Entity.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/Entity.cs
deleted file mode 100644
index 6868071dbef..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/Entity.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class Entity
-{
- public int Id { get; set; }
- public string Name { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithAdditionalProperty.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithAdditionalProperty.cs
deleted file mode 100644
index 3cc4a830b0f..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithAdditionalProperty.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class EntityWithAdditionalProperty
-{
- public int Id { get; set; }
- public string Name { get; set; }
- public int AdditionalProperty { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithTwoAdditionalProperties.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithTwoAdditionalProperties.cs
deleted file mode 100644
index b29334dd227..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/EntityWithTwoAdditionalProperties.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class EntityWithTwoAdditionalProperties
-{
- public int Id { get; set; }
- public string Name { get; set; }
- public int AdditionalProperty1 { get; set; }
- public int AdditionalProperty2 { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/StoredProcedureUpdateContext.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/StoredProcedureUpdateContext.cs
deleted file mode 100644
index 4e976c1af93..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/StoredProcedureUpdateContext.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class StoredProcedureUpdateContext : PoolableDbContext
-{
- public StoredProcedureUpdateContext(DbContextOptions options)
- : base(options)
- {
- }
-
- public DbSet WithOutputParameter
- => Set(nameof(WithOutputParameter));
-
- public DbSet WithResultColumn
- => Set(nameof(WithResultColumn));
-
- public DbSet WithTwoResultColumns
- => Set(nameof(WithTwoResultColumns));
-
- public DbSet WithOutputParameterAndResultColumn
- => Set(nameof(WithOutputParameterAndResultColumn));
-
- public DbSet WithOutputParameterAndRowsAffectedResultColumn
- => Set(nameof(WithOutputParameterAndRowsAffectedResultColumn));
-
- public DbSet WithTwoInputParameters
- => Set(nameof(WithTwoInputParameters));
-
- public DbSet WithRowsAffectedParameter
- => Set(nameof(WithRowsAffectedParameter));
-
- public DbSet WithRowsAffectedResultColumn
- => Set(nameof(WithRowsAffectedResultColumn));
-
- public DbSet WithRowsAffectedReturnValue
- => Set(nameof(WithRowsAffectedReturnValue));
-
- public DbSet WithStoreGeneratedConcurrencyTokenAsInOutParameter
- => Set(nameof(WithStoreGeneratedConcurrencyTokenAsInOutParameter));
-
- public DbSet WithStoreGeneratedConcurrencyTokenAsTwoParameters
- => Set(nameof(WithStoreGeneratedConcurrencyTokenAsTwoParameters));
-
- public DbSet WithUserManagedConcurrencyToken
- => Set(nameof(WithUserManagedConcurrencyToken));
-
- public DbSet WithOriginalAndCurrentValueOnNonConcurrencyToken
- => Set(nameof(WithOriginalAndCurrentValueOnNonConcurrencyToken));
-
- public DbSet WithInputOrOutputParameter
- => Set(nameof(WithInputOrOutputParameter));
-
- public DbSet TphParent { get; set; }
- public DbSet TphChild { get; set; }
- public DbSet TptParent { get; set; }
- public DbSet TptChild { get; set; }
- public DbSet TptMixedParent { get; set; }
- public DbSet TptMixedChild { get; set; }
- public DbSet TpcParent { get; set; }
- public DbSet TpcChild { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcChild.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcChild.cs
deleted file mode 100644
index dc68342567f..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcChild.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TpcChild : TpcParent
-{
- public int ChildProperty { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcParent.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcParent.cs
deleted file mode 100644
index 801a45b95d2..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TpcParent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TpcParent
-{
- public int Id { get; set; }
- public string Name { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild1.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild1.cs
deleted file mode 100644
index 1278bb97aca..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild1.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TphChild1 : TphParent
-{
- public int Child1Property { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild2.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild2.cs
deleted file mode 100644
index 3fdf4059531..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphChild2.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TphChild2 : TphParent
-{
- public int Child2InputProperty { get; set; }
- public int Child2OutputParameterProperty { get; set; }
- public int Child2ResultColumnProperty { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphParent.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphParent.cs
deleted file mode 100644
index b8583fe1525..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TphParent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TphParent
-{
- public int Id { get; set; }
- public string Name { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptChild.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptChild.cs
deleted file mode 100644
index 3d3d2e8266c..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptChild.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TptChild : TptParent
-{
- public int ChildProperty { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedChild.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedChild.cs
deleted file mode 100644
index b37fc9fc324..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedChild.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TptMixedChild : TptMixedParent
-{
- public int ChildProperty { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedParent.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedParent.cs
deleted file mode 100644
index 209f056bee1..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptMixedParent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TptMixedParent
-{
- public int Id { get; set; }
- public string Name { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptParent.cs b/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptParent.cs
deleted file mode 100644
index fd5646fe143..00000000000
--- a/test/EFCore.Relational.Specification.Tests/TestModels/StoredProcedureUpdateModel/TptParent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-public class TptParent
-{
- public int Id { get; set; }
- public string Name { get; set; }
-}
diff --git a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateFixtureBase.cs b/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateFixtureBase.cs
deleted file mode 100644
index dfa204c5d1e..00000000000
--- a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateFixtureBase.cs
+++ /dev/null
@@ -1,290 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
-
-namespace Microsoft.EntityFrameworkCore.Update;
-
-#nullable enable
-
-public abstract class StoredProcedureUpdateFixtureBase : SharedStoreFixtureBase
-{
- protected override string StoreName
- => "StoredProcedureUpdateTest";
-
- protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context)
- {
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithOutputParameter))
- .InsertUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithOutputParameter) + "_Insert",
- spb => spb
- .HasParameter(w => w.Name)
- .HasParameter(w => w.Id, pb => pb.IsOutput()))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithOutputParameter) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name))
- .DeleteUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithOutputParameter) + "_Delete",
- spb => spb.HasOriginalValueParameter(w => w.Id));
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithResultColumn))
- .InsertUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithResultColumn) + "_Insert", spb => spb
- .HasParameter(w => w.Name)
- .HasResultColumn(w => w.Id));
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithTwoResultColumns),
- b =>
- {
- b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
-
- b.InsertUsingStoredProcedure(
- "WithTwoResultColumns_Insert", spb => spb
- .HasParameter(w => w.Name)
- .HasResultColumn(w => w.AdditionalProperty)
- .HasResultColumn(w => w.Id));
- });
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithOutputParameterAndResultColumn),
- b =>
- {
- b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
-
- b.InsertUsingStoredProcedure(
- "WithOutputParameterAndResultColumn_Insert", spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter(w => w.Name)
- .HasResultColumn(w => w.AdditionalProperty));
- });
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithOutputParameterAndRowsAffectedResultColumn),
- b =>
- {
- b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
-
- b.UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithOutputParameterAndRowsAffectedResultColumn) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name)
- .HasParameter(w => w.AdditionalProperty, pb => pb.IsOutput())
- .HasRowsAffectedResultColumn());
- });
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithTwoInputParameters))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithTwoInputParameters) + "_Update", spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name)
- .HasParameter(w => w.AdditionalProperty));
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithRowsAffectedParameter))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithRowsAffectedParameter) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name)
- .HasRowsAffectedParameter());
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithRowsAffectedResultColumn))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithRowsAffectedResultColumn) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name)
- .HasRowsAffectedResultColumn());
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithRowsAffectedReturnValue))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithRowsAffectedReturnValue) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name)
- .HasRowsAffectedReturnValue());
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithStoreGeneratedConcurrencyTokenAsInOutParameter),
- b =>
- {
- ConfigureStoreGeneratedConcurrencyToken(b, "ConcurrencyToken");
-
- b.UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithStoreGeneratedConcurrencyTokenAsInOutParameter) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasOriginalValueParameter("ConcurrencyToken", pb => pb.IsInputOutput())
- .HasParameter(w => w.Name)
- .HasRowsAffectedParameter());
- });
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithStoreGeneratedConcurrencyTokenAsTwoParameters),
- b =>
- {
- ConfigureStoreGeneratedConcurrencyToken(b, "ConcurrencyToken");
-
- b.UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithStoreGeneratedConcurrencyTokenAsTwoParameters) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasOriginalValueParameter("ConcurrencyToken", pb => pb.HasName("ConcurrencyTokenIn"))
- .HasParameter(w => w.Name)
- .HasParameter(
- "ConcurrencyToken", pb => pb
- .HasName("ConcurrencyTokenOut")
- .IsOutput())
- .HasRowsAffectedParameter());
- });
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithUserManagedConcurrencyToken),
- b =>
- {
- b.Property(e => e.AdditionalProperty).IsConcurrencyToken();
-
- b.UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithUserManagedConcurrencyToken) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasOriginalValueParameter(w => w.AdditionalProperty, pb => pb.HasName("ConcurrencyTokenOriginal"))
- .HasParameter(w => w.Name)
- .HasParameter(w => w.AdditionalProperty, pb => pb.HasName("ConcurrencyTokenCurrent"))
- .HasRowsAffectedParameter());
- });
-
- modelBuilder.SharedTypeEntity(nameof(StoredProcedureUpdateContext.WithOriginalAndCurrentValueOnNonConcurrencyToken))
- .UpdateUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithOriginalAndCurrentValueOnNonConcurrencyToken) + "_Update",
- spb => spb
- .HasOriginalValueParameter(w => w.Id)
- .HasParameter(w => w.Name, pb => pb.HasName("NameCurrent"))
- .HasOriginalValueParameter(w => w.Name, pb => pb.HasName("NameOriginal")));
-
- modelBuilder.SharedTypeEntity(
- nameof(StoredProcedureUpdateContext.WithInputOrOutputParameter),
- b =>
- {
- b.Property(w => w.Name).IsRequired().ValueGeneratedOnAdd();
-
- b.InsertUsingStoredProcedure(
- nameof(StoredProcedureUpdateContext.WithInputOrOutputParameter) + "_Insert",
- spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter(w => w.Name, pb => pb.IsInputOutput()));
- });
-
- modelBuilder.Entity();
-
- modelBuilder.Entity(
- b =>
- {
- b.Property(w => w.Child2OutputParameterProperty).HasDefaultValue(8);
- b.Property(w => w.Child2ResultColumnProperty).HasDefaultValue(9);
- });
-
- modelBuilder.Entity(
- b =>
- {
- b.ToTable("Tph");
-
- b.InsertUsingStoredProcedure(
- "Tph_Insert",
- spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter("Discriminator")
- .HasParameter(w => w.Name)
- .HasParameter(nameof(TphChild2.Child2InputProperty))
- .HasParameter(nameof(TphChild2.Child2OutputParameterProperty), o => o.IsOutput())
- .HasParameter(nameof(TphChild1.Child1Property))
- .HasResultColumn(nameof(TphChild2.Child2ResultColumnProperty)));
- });
-
- modelBuilder.Entity(
- b =>
- {
- b.UseTptMappingStrategy();
-
- b.InsertUsingStoredProcedure(
- "TptParent_Insert",
- spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter(w => w.Name));
- });
-
- // TODO: The following fails validation:
- // The entity type 'TptChild' is mapped to the stored procedure 'TptChild_Insert', however the store-generated properties {'Id'} are not mapped to any output parameter or result column.
- modelBuilder.Entity()
- .InsertUsingStoredProcedure(
- "TptChild_Insert",
- spb => spb
- .HasParameter(w => w.Id)
- .HasParameter(w => w.ChildProperty));
-
- modelBuilder.Entity(
- b =>
- {
- b.UseTptMappingStrategy();
-
- b.InsertUsingStoredProcedure(
- "TptMixedParent_Insert",
- spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter(w => w.Name));
- });
-
- // No sproc mapping for TptMixedChild, use regular SQL
-
- modelBuilder.Entity().UseTpcMappingStrategy();
-
- modelBuilder.Entity()
- .UseTpcMappingStrategy()
- .InsertUsingStoredProcedure(
- "TpcChild_Insert",
- spb => spb
- .HasParameter(w => w.Id, pb => pb.IsOutput())
- .HasParameter(w => w.Name)
- .HasParameter(w => w.ChildProperty));
- }
-
- ///
- /// A method to be implement by the provider, to set up a store-generated concurrency token shadow property with the given name.
- ///
- protected abstract void ConfigureStoreGeneratedConcurrencyToken(EntityTypeBuilder entityTypeBuilder, string propertyName);
-
- public virtual void CleanData()
- {
- using var context = CreateContext();
-
- context.WithOutputParameter.RemoveRange(context.WithOutputParameter);
- context.WithResultColumn.RemoveRange(context.WithResultColumn);
- context.WithTwoResultColumns.RemoveRange(context.WithTwoResultColumns);
- context.WithOutputParameterAndResultColumn.RemoveRange(context.WithOutputParameterAndResultColumn);
- context.WithTwoInputParameters.RemoveRange(context.WithTwoInputParameters);
- context.WithRowsAffectedParameter.RemoveRange(context.WithRowsAffectedParameter);
- context.WithRowsAffectedResultColumn.RemoveRange(context.WithRowsAffectedResultColumn);
- context.WithRowsAffectedReturnValue.RemoveRange(context.WithRowsAffectedReturnValue);
- context.WithStoreGeneratedConcurrencyTokenAsInOutParameter.RemoveRange(context.WithStoreGeneratedConcurrencyTokenAsInOutParameter);
- context.WithStoreGeneratedConcurrencyTokenAsTwoParameters.RemoveRange(context.WithStoreGeneratedConcurrencyTokenAsTwoParameters);
- context.WithUserManagedConcurrencyToken.RemoveRange(context.WithUserManagedConcurrencyToken);
- context.WithOriginalAndCurrentValueOnNonConcurrencyToken.RemoveRange(context.WithOriginalAndCurrentValueOnNonConcurrencyToken);
- context.WithInputOrOutputParameter.RemoveRange(context.WithInputOrOutputParameter);
- context.TphParent.RemoveRange(context.TphParent);
- context.TphChild.RemoveRange(context.TphChild);
- context.TptParent.RemoveRange(context.TptParent);
- context.TptChild.RemoveRange(context.TptChild);
- context.TptMixedParent.RemoveRange(context.TptMixedParent);
- context.TptMixedChild.RemoveRange(context.TptMixedChild);
- context.TpcParent.RemoveRange(context.TpcParent);
- context.TpcChild.RemoveRange(context.TpcChild);
-
- context.SaveChanges();
- }
-
- public TestSqlLoggerFactory TestSqlLoggerFactory
- => (TestSqlLoggerFactory)ListLoggerFactory;
-}
diff --git a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs b/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs
index 6a7abce9896..2f7be4ce72d 100644
--- a/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs
+++ b/test/EFCore.Relational.Specification.Tests/Update/StoredProcedureUpdateTestBase.cs
@@ -1,119 +1,183 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.EntityFrameworkCore.TestModels.StoredProcedureUpdateModel;
+using System.Text.RegularExpressions;
namespace Microsoft.EntityFrameworkCore.Update;
-#nullable enable
-
-public class StoredProcedureUpdateTestBase : IClassFixture
- where TFixture : StoredProcedureUpdateFixtureBase
+public abstract class StoredProcedureUpdateTestBase : NonSharedModelTestBase
{
- protected StoredProcedureUpdateTestBase(TFixture fixture)
- {
- Fixture = fixture;
-
- fixture.CleanData();
-
- ClearLog();
- }
+ protected override string StoreName
+ => "StoredProcedureUpdateTest";
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Insert_with_output_parameter(bool async)
+ public abstract Task Insert_with_output_parameter(bool async);
+
+ protected async Task Insert_with_output_parameter(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.Id, pb => pb.IsOutput())),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var newEntity1 = new Entity { Name = "New" };
- context.WithOutputParameter.Add(newEntity1);
+ context.Set().Add(newEntity1);
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("New", context.WithOutputParameter.Single(b => b.Id == newEntity1.Id).Name);
+ Assert.Equal("New", context.Set().Single(b => b.Id == newEntity1.Id).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Insert_twice_with_output_parameter(bool async)
+ public abstract Task Insert_twice_with_output_parameter(bool async);
+
+ protected async Task Insert_twice_with_output_parameter(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.Id, pb => pb.IsOutput())),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var (newEntity1, newEntity2) = (new Entity { Name = "New1" }, new Entity { Name = "New2" });
- context.WithOutputParameter.AddRange(newEntity1, newEntity2);
+ context.Set().AddRange(newEntity1, newEntity2);
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("New1", context.WithOutputParameter.Single(b => b.Id == newEntity1.Id).Name);
- Assert.Equal("New2", context.WithOutputParameter.Single(b => b.Id == newEntity2.Id).Name);
+ Assert.Equal("New1", context.Set().Single(b => b.Id == newEntity1.Id).Name);
+ Assert.Equal("New2", context.Set().Single(b => b.Id == newEntity2.Id).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Insert_with_result_column(bool async)
+ public abstract Task Insert_with_result_column(bool async);
+
+ protected async Task Insert_with_result_column(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity().InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert", spb => spb
+ .HasParameter(w => w.Name)
+ .HasResultColumn(w => w.Id)),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Foo" };
- context.WithResultColumn.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Foo", context.WithResultColumn.Single(b => b.Id == entity.Id).Name);
+ Assert.Equal("Foo", context.Set().Single(b => b.Id == entity.Id).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Insert_with_two_result_columns(bool async)
+ public abstract Task Insert_with_two_result_columns(bool async);
+
+ protected async Task Insert_with_two_result_columns(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
+
+ b.InsertUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Insert", spb => spb
+ .HasParameter(w => w.Name)
+ .HasResultColumn(w => w.AdditionalProperty)
+ .HasResultColumn(w => w.Id));
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new EntityWithAdditionalProperty { Name = "Foo" };
- context.WithTwoResultColumns.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
Assert.Equal(1, entity.Id);
Assert.Equal(8, entity.AdditionalProperty);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Foo", context.WithTwoResultColumns.Single(b => b.Id == entity.Id).Name);
+ Assert.Equal("Foo", context.Set().Single(b => b.Id == entity.Id).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Insert_with_output_parameter_and_result_column(bool async)
+ public abstract Task Insert_with_output_parameter_and_result_column(bool async);
+
+ protected async Task Insert_with_output_parameter_and_result_column(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
+
+ b.InsertUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Insert", spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name)
+ .HasResultColumn(w => w.AdditionalProperty));
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new EntityWithAdditionalProperty { Name = "Foo" };
- context.WithOutputParameterAndResultColumn.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
Assert.Equal(8, entity.AdditionalProperty);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Foo", context.WithOutputParameterAndResultColumn.Single(b => b.Id == entity.Id).Name);
+ Assert.Equal("Foo", context.Set().Single(b => b.Id == entity.Id).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Update(bool async)
+ public abstract Task Update(bool async);
+
+ protected async Task Update(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity().UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithOutputParameter.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
ClearLog();
@@ -121,20 +185,30 @@ public virtual async Task Update(bool async)
entity.Name = "Updated";
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Updated", (await context.WithOutputParameter.SingleAsync(w => w.Id == entity.Id)).Name);
+ Assert.Equal("Updated", (await context.Set().SingleAsync(w => w.Id == entity.Id)).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Update_partial(bool async)
+ public abstract Task Update_partial(bool async);
+
+ protected async Task Update_partial(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity().UpdateUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Update", spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.AdditionalProperty)),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new EntityWithAdditionalProperty { Name = "Foo", AdditionalProperty = 8 };
- context.WithTwoInputParameters.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
entity.Name = "Updated";
@@ -143,9 +217,9 @@ public virtual async Task Update_partial(bool async)
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var actual = await context.WithTwoInputParameters.SingleAsync(w => w.Id == entity.Id);
+ var actual = await context.Set().SingleAsync(w => w.Id == entity.Id);
Assert.Equal("Updated", actual.Name);
Assert.Equal(8, actual.AdditionalProperty);
@@ -154,12 +228,30 @@ public virtual async Task Update_partial(bool async)
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Update_with_output_parameter_and_rows_affected_result_column(bool async)
+ public abstract Task Update_with_output_parameter_and_rows_affected_result_column(bool async);
+
+ protected async Task Update_with_output_parameter_and_rows_affected_result_column(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
+
+ b.UpdateUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.AdditionalProperty, pb => pb.IsOutput())
+ .HasRowsAffectedResultColumn());
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new EntityWithAdditionalProperty { Name = "Foo" };
- context.WithOutputParameterAndRowsAffectedResultColumn.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
entity.Name = "Updated";
@@ -168,9 +260,9 @@ public virtual async Task Update_with_output_parameter_and_rows_affected_result_
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var actual = await context.WithOutputParameterAndRowsAffectedResultColumn.SingleAsync(w => w.Id == entity.Id);
+ var actual = await context.Set().SingleAsync(w => w.Id == entity.Id);
Assert.Equal("Updated", actual.Name);
Assert.Equal(8, actual.AdditionalProperty);
@@ -179,18 +271,36 @@ public virtual async Task Update_with_output_parameter_and_rows_affected_result_
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Update_with_output_parameter_and_rows_affected_result_column_concurrency_failure(bool async)
+ public abstract Task Update_with_output_parameter_and_rows_affected_result_column_concurrency_failure(bool async);
+
+ protected async Task Update_with_output_parameter_and_rows_affected_result_column_concurrency_failure(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.AdditionalProperty).HasComputedColumnSql("8");
+
+ b.UpdateUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.AdditionalProperty, pb => pb.IsOutput())
+ .HasRowsAffectedResultColumn());
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new EntityWithAdditionalProperty { Name = "Initial" };
- context1.WithOutputParameterAndRowsAffectedResultColumn.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithOutputParameterAndRowsAffectedResultColumn.SingleAsync(w => w.Name == "Initial");
- context2.WithOutputParameterAndRowsAffectedResultColumn.Remove(entity2);
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
+ context2.Set().Remove(entity2);
await context2.SaveChangesAsync();
}
@@ -205,56 +315,91 @@ public virtual async Task Update_with_output_parameter_and_rows_affected_result_
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Delete(bool async)
+ public abstract Task Delete(bool async);
+
+ protected async Task Delete(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .DeleteUsingStoredProcedure(
+ nameof(Entity) + "_Delete",
+ spb => spb.HasOriginalValueParameter(w => w.Id)),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithOutputParameter.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
ClearLog();
- context.WithOutputParameter.Remove(entity);
+ context.Set().Remove(entity);
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal(0, await context.WithOutputParameter.CountAsync(b => b.Name == "Initial"));
+ Assert.Equal(0, await context.Set().CountAsync(b => b.Name == "Initial"));
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Delete_and_insert(bool async)
+ public abstract Task Delete_and_insert(bool async);
+
+ protected async Task Delete_and_insert(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.Id, pb => pb.IsOutput()))
+ .DeleteUsingStoredProcedure(
+ nameof(Entity) + "_Delete",
+ spb => spb.HasOriginalValueParameter(w => w.Id)),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Entity1" };
- context.WithOutputParameter.Add(entity1);
+ context.Set().Add(entity1);
await context.SaveChangesAsync();
ClearLog();
- context.WithOutputParameter.Remove(entity1);
- context.WithOutputParameter.Add(new Entity { Name = "Entity2" });
+ context.Set().Remove(entity1);
+ context.Set().Add(new Entity { Name = "Entity2" });
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal(0, await context.WithOutputParameter.CountAsync(b => b.Name == "Entity1"));
- Assert.Equal(1, await context.WithOutputParameter.CountAsync(b => b.Name == "Entity2"));
+ Assert.Equal(0, await context.Set().CountAsync(b => b.Name == "Entity1"));
+ Assert.Equal(1, await context.Set().CountAsync(b => b.Name == "Entity2"));
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_parameter(bool async)
+ public abstract Task Rows_affected_parameter(bool async);
+
+ protected async Task Rows_affected_parameter(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedParameter()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithRowsAffectedParameter.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
ClearLog();
@@ -263,26 +408,38 @@ public virtual async Task Rows_affected_parameter(bool async)
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Updated", (await context.WithRowsAffectedParameter.SingleAsync(w => w.Id == entity.Id)).Name);
+ Assert.Equal("Updated", (await context.Set().SingleAsync(w => w.Id == entity.Id)).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_parameter_and_concurrency_failure(bool async)
+ public abstract Task Rows_affected_parameter_and_concurrency_failure(bool async);
+
+ protected async Task Rows_affected_parameter_and_concurrency_failure(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedParameter()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Initial" };
- context1.WithRowsAffectedParameter.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithRowsAffectedParameter.SingleAsync(w => w.Name == "Initial");
- context2.WithRowsAffectedParameter.Remove(entity2);
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
+ context2.Set().Remove(entity2);
await context2.SaveChangesAsync();
}
@@ -297,12 +454,24 @@ public virtual async Task Rows_affected_parameter_and_concurrency_failure(bool a
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_result_column(bool async)
+ public abstract Task Rows_affected_result_column(bool async);
+
+ protected async Task Rows_affected_result_column(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedResultColumn()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithRowsAffectedResultColumn.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
ClearLog();
@@ -311,26 +480,38 @@ public virtual async Task Rows_affected_result_column(bool async)
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Updated", (await context.WithRowsAffectedResultColumn.SingleAsync(w => w.Id == entity.Id)).Name);
+ Assert.Equal("Updated", (await context.Set().SingleAsync(w => w.Id == entity.Id)).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_result_column_and_concurrency_failure(bool async)
+ public abstract Task Rows_affected_result_column_and_concurrency_failure(bool async);
+
+ protected async Task Rows_affected_result_column_and_concurrency_failure(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedResultColumn()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Initial" };
- context1.WithRowsAffectedResultColumn.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithRowsAffectedResultColumn.SingleAsync(w => w.Name == "Initial");
- context2.WithRowsAffectedResultColumn.Remove(entity2);
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
+ context2.Set().Remove(entity2);
await context2.SaveChangesAsync();
}
@@ -345,12 +526,24 @@ public virtual async Task Rows_affected_result_column_and_concurrency_failure(bo
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_return_value(bool async)
+ public abstract Task Rows_affected_return_value(bool async);
+
+ protected async Task Rows_affected_return_value(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedReturnValue()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithRowsAffectedReturnValue.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
ClearLog();
@@ -359,26 +552,38 @@ public virtual async Task Rows_affected_return_value(bool async)
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- Assert.Equal("Updated", (await context.WithRowsAffectedReturnValue.SingleAsync(w => w.Id == entity.Id)).Name);
+ Assert.Equal("Updated", (await context.Set().SingleAsync(w => w.Id == entity.Id)).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Rows_affected_return_value_and_concurrency_failure(bool async)
+ public abstract Task Rows_affected_return_value_and_concurrency_failure(bool async);
+
+ protected async Task Rows_affected_return_value_and_concurrency_failure(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedReturnValue()),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Initial" };
- context1.WithRowsAffectedReturnValue.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithRowsAffectedReturnValue.SingleAsync(w => w.Name == "Initial");
- context2.WithRowsAffectedReturnValue.Remove(entity2);
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
+ context2.Set().Remove(entity2);
await SaveChanges(context2, async);
}
@@ -393,17 +598,35 @@ public virtual async Task Rows_affected_return_value_and_concurrency_failure(boo
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Store_generated_concurrency_token_as_in_out_parameter(bool async)
+ public abstract Task Store_generated_concurrency_token_as_in_out_parameter(bool async);
+
+ protected async Task Store_generated_concurrency_token_as_in_out_parameter(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ ConfigureStoreGeneratedConcurrencyToken(b, "ConcurrencyToken");
+
+ b.UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasOriginalValueParameter("ConcurrencyToken", pb => pb.IsInputOutput())
+ .HasParameter(w => w.Name)
+ .HasRowsAffectedParameter());
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Initial" };
- context1.WithStoreGeneratedConcurrencyTokenAsInOutParameter.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithStoreGeneratedConcurrencyTokenAsInOutParameter.SingleAsync(w => w.Name == "Initial");
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
entity2.Name = "Preempted";
await SaveChanges(context2, async);
}
@@ -419,17 +642,39 @@ public virtual async Task Store_generated_concurrency_token_as_in_out_parameter(
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Store_generated_concurrency_token_as_two_parameters(bool async)
+ public abstract Task Store_generated_concurrency_token_as_two_parameters(bool async);
+
+ protected async Task Store_generated_concurrency_token_as_two_parameters(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ ConfigureStoreGeneratedConcurrencyToken(b, "ConcurrencyToken");
+
+ b.UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasOriginalValueParameter("ConcurrencyToken", pb => pb.HasName("ConcurrencyTokenIn"))
+ .HasParameter(w => w.Name)
+ .HasParameter(
+ "ConcurrencyToken", pb => pb
+ .HasName("ConcurrencyTokenOut")
+ .IsOutput())
+ .HasRowsAffectedParameter());
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new Entity { Name = "Initial" };
- context1.WithStoreGeneratedConcurrencyTokenAsTwoParameters.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithStoreGeneratedConcurrencyTokenAsTwoParameters.SingleAsync(w => w.Name == "Initial");
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
entity2.Name = "Preempted";
await SaveChanges(context2, async);
}
@@ -445,24 +690,43 @@ public virtual async Task Store_generated_concurrency_token_as_two_parameters(bo
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task User_managed_concurrency_token(bool async)
+ public abstract Task User_managed_concurrency_token(bool async);
+
+ protected async Task User_managed_concurrency_token(bool async, string createSprocSql)
{
- await using var context1 = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(e => e.AdditionalProperty).IsConcurrencyToken();
+
+ b.UpdateUsingStoredProcedure(
+ nameof(EntityWithAdditionalProperty) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasOriginalValueParameter(w => w.AdditionalProperty, pb => pb.HasName("ConcurrencyTokenOriginal"))
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.AdditionalProperty, pb => pb.HasName("ConcurrencyTokenCurrent"))
+ .HasRowsAffectedParameter());
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context1 = contextFactory.CreateContext();
var entity1 = new EntityWithAdditionalProperty
{
Name = "Initial", AdditionalProperty = 8 // The concurrency token
};
- context1.WithUserManagedConcurrencyToken.Add(entity1);
+ context1.Set().Add(entity1);
await context1.SaveChangesAsync();
entity1.Name = "Updated";
entity1.AdditionalProperty = 9;
- await using (var context2 = CreateContext())
+ await using (var context2 = contextFactory.CreateContext())
{
- var entity2 = await context2.WithUserManagedConcurrencyToken.SingleAsync(w => w.Name == "Initial");
+ var entity2 = await context2.Set().SingleAsync(w => w.Name == "Initial");
entity2.Name = "Preempted";
entity2.AdditionalProperty = 999;
await SaveChanges(context2, async);
@@ -476,13 +740,25 @@ public virtual async Task User_managed_concurrency_token(bool async)
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Original_and_current_value_on_non_concurrency_token(bool async)
+ public abstract Task Original_and_current_value_on_non_concurrency_token(bool async);
+
+ protected async Task Original_and_current_value_on_non_concurrency_token(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity()
+ .UpdateUsingStoredProcedure(
+ nameof(Entity) + "_Update",
+ spb => spb
+ .HasOriginalValueParameter(w => w.Id)
+ .HasParameter(w => w.Name, pb => pb.HasName("NameCurrent"))
+ .HasOriginalValueParameter(w => w.Name, pb => pb.HasName("NameOriginal"))),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithOriginalAndCurrentValueOnNonConcurrencyToken.Add(entity);
+ context.Set().Add(entity);
await context.SaveChangesAsync();
entity.Name = "Updated";
@@ -491,67 +767,132 @@ public virtual async Task Original_and_current_value_on_non_concurrency_token(bo
await SaveChanges(context, async);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
Assert.Equal(
"Updated",
- (await context.WithOriginalAndCurrentValueOnNonConcurrencyToken.SingleAsync(w => w.Id == entity.Id)).Name);
+ (await context.Set().SingleAsync(w => w.Id == entity.Id)).Name);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Input_or_output_parameter_with_input(bool async)
+ public abstract Task Input_or_output_parameter_with_input(bool async);
+
+ protected async Task Input_or_output_parameter_with_input(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.Name).IsRequired().ValueGeneratedOnAdd();
+
+ b.InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name, pb => pb.IsInputOutput()));
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity { Name = "Initial" };
- context.WithInputOrOutputParameter.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
Assert.Equal("Initial", entity.Name);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
Assert.Same(
- entity, await context.WithInputOrOutputParameter.SingleAsync(w => w.Id == entity.Id && w.Name == "Initial"));
+ entity, await context.Set().SingleAsync(w => w.Id == entity.Id && w.Name == "Initial"));
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Input_or_output_parameter_with_output(bool async)
+ public abstract Task Input_or_output_parameter_with_output(bool async);
+
+ protected async Task Input_or_output_parameter_with_output(bool async, string createSprocSql)
{
- await using var context = CreateContext();
+ var contextFactory = await InitializeAsync(
+ modelBuilder => modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.Name).IsRequired().ValueGeneratedOnAdd();
+
+ b.InsertUsingStoredProcedure(
+ nameof(Entity) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name, pb => pb.IsInputOutput()));
+ }),
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
var entity = new Entity();
- context.WithInputOrOutputParameter.Add(entity);
+ context.Set().Add(entity);
await SaveChanges(context, async);
Assert.Equal("Some default value", entity.Name);
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
Assert.Same(
- entity, await context.WithInputOrOutputParameter.SingleAsync(w => w.Id == entity.Id && w.Name == "Some default value"));
+ entity, await context.Set().SingleAsync(w => w.Id == entity.Id && w.Name == "Some default value"));
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Tph(bool async)
- {
- await using var context = CreateContext();
+ public abstract Task Tph(bool async);
- var entity1 = new TphChild1 { Name = "Child", Child1Property = 8 };
- context.TphChild.Add(entity1);
+ protected async Task Tph(bool async, string createSprocSql)
+ {
+ var contextFactory = await InitializeAsync(
+ modelBuilder =>
+ {
+ modelBuilder.Entity();
+
+ modelBuilder.Entity(
+ b =>
+ {
+ b.Property(w => w.Child2OutputParameterProperty).HasDefaultValue(8);
+ b.Property(w => w.Child2ResultColumnProperty).HasDefaultValue(9);
+ });
+
+ modelBuilder.Entity(
+ b =>
+ {
+ b.ToTable("Tph");
+
+ b.InsertUsingStoredProcedure(
+ "Tph_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter("Discriminator")
+ .HasParameter(w => w.Name)
+ .HasParameter(nameof(Child2.Child2InputProperty))
+ .HasParameter(nameof(Child2.Child2OutputParameterProperty), o => o.IsOutput())
+ .HasParameter(nameof(Child1.Child1Property))
+ .HasResultColumn(nameof(Child2.Child2ResultColumnProperty)));
+ });
+ },
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
+
+ var entity1 = new Child1 { Name = "Child", Child1Property = 8 };
+ context.Set().Add(entity1);
await SaveChanges(context, async);
context.ChangeTracker.Clear();
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var entity2 = context.TphChild.Single(b => b.Id == entity1.Id);
+ var entity2 = context.Set().Single(b => b.Id == entity1.Id);
Assert.Equal("Child", entity2.Name);
Assert.Equal(8, entity2.Child1Property);
@@ -560,68 +901,170 @@ public virtual async Task Tph(bool async)
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Tpt(bool async)
- {
- await using var context = CreateContext();
+ public abstract Task Tpt(bool async);
- var entity1 = new TptChild { Name = "Child", ChildProperty = 8 };
- context.TptChild.Add(entity1);
+ protected async Task Tpt(bool async, string createSprocSql)
+ {
+ var contextFactory = await InitializeAsync(
+ modelBuilder =>
+ {
+ modelBuilder.Entity(
+ b =>
+ {
+ b.UseTptMappingStrategy();
+
+ b.InsertUsingStoredProcedure(
+ "Parent_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name));
+ });
+
+ modelBuilder.Entity()
+ .InsertUsingStoredProcedure(
+ nameof(Child1) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Id)
+ .HasParameter(w => w.Child1Property));
+ },
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
+
+ var entity1 = new Child1 { Name = "Child", Child1Property = 8 };
+ context.Set().Add(entity1);
await SaveChanges(context, async);
context.ChangeTracker.Clear();
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var entity2 = context.TptChild.Single(b => b.Id == entity1.Id);
+ var entity2 = context.Set().Single(b => b.Id == entity1.Id);
Assert.Equal("Child", entity2.Name);
- Assert.Equal(8, entity2.ChildProperty);
+ Assert.Equal(8, entity2.Child1Property);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Tpt_mixed_sproc_and_non_sproc(bool async)
- {
- await using var context = CreateContext();
+ public abstract Task Tpt_mixed_sproc_and_non_sproc(bool async);
- var entity1 = new TptMixedChild { Name = "Child", ChildProperty = 8 };
- context.TptMixedChild.Add(entity1);
+ protected async Task Tpt_mixed_sproc_and_non_sproc(bool async, string createSprocSql)
+ {
+ var contextFactory = await InitializeAsync(
+ modelBuilder =>
+ {
+ modelBuilder.Entity(
+ b =>
+ {
+ b.UseTptMappingStrategy();
+
+ b.InsertUsingStoredProcedure(
+ nameof(Parent) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name));
+ });
+
+ // No sproc mapping for Child1, use regular SQL
+ modelBuilder.Entity();
+ },
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
+
+ var entity1 = new Child1 { Name = "Child", Child1Property = 8 };
+ context.Set().Add(entity1);
await SaveChanges(context, async);
context.ChangeTracker.Clear();
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var entity2 = context.TptMixedChild.Single(b => b.Id == entity1.Id);
+ var entity2 = context.Set().Single(b => b.Id == entity1.Id);
Assert.Equal("Child", entity2.Name);
- Assert.Equal(8, entity2.ChildProperty);
+ Assert.Equal(8, entity2.Child1Property);
}
}
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual async Task Tpc(bool async)
- {
- await using var context = CreateContext();
+ public abstract Task Tpc(bool async);
- var entity1 = new TpcChild { Name = "Child", ChildProperty = 8 };
- context.TpcChild.Add(entity1);
+ protected async Task Tpc(bool async, string createSprocSql)
+ {
+ var contextFactory = await InitializeAsync(
+ modelBuilder =>
+ {
+ modelBuilder.Entity().UseTpcMappingStrategy();
+
+ modelBuilder.Entity()
+ .UseTpcMappingStrategy()
+ .InsertUsingStoredProcedure(
+ nameof(Child1) + "_Insert",
+ spb => spb
+ .HasParameter(w => w.Id, pb => pb.IsOutput())
+ .HasParameter(w => w.Name)
+ .HasParameter(w => w.Child1Property));
+ },
+ seed: ctx => CreateStoredProcedures(ctx, createSprocSql));
+
+ await using var context = contextFactory.CreateContext();
+
+ var entity1 = new Child1 { Name = "Child", Child1Property = 8 };
+ context.Set().Add(entity1);
await SaveChanges(context, async);
context.ChangeTracker.Clear();
- using (Fixture.TestSqlLoggerFactory.SuspendRecordingEvents())
+ using (TestSqlLoggerFactory.SuspendRecordingEvents())
{
- var entity2 = context.TpcChild.Single(b => b.Id == entity1.Id);
+ var entity2 = context.Set().Single(b => b.Id == entity1.Id);
Assert.Equal("Child", entity2.Name);
- Assert.Equal(8, entity2.ChildProperty);
+ Assert.Equal(8, entity2.Child1Property);
}
}
- private async Task SaveChanges(StoredProcedureUpdateContext context, bool async)
+ ///
+ /// A method to be implement by the provider, to set up a store-generated concurrency token shadow property with the given name.
+ ///
+ protected abstract void ConfigureStoreGeneratedConcurrencyToken(EntityTypeBuilder entityTypeBuilder, string propertyName);
+
+ protected class Entity
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ protected class EntityWithAdditionalProperty
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public int AdditionalProperty { get; set; }
+ }
+
+ protected class Child1 : Parent
+ {
+ public int Child1Property { get; set; }
+ }
+
+ protected class Child2 : Parent
+ {
+ public int Child2InputProperty { get; set; }
+ public int Child2OutputParameterProperty { get; set; }
+ public int Child2ResultColumnProperty { get; set; }
+ }
+
+ protected class Parent
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ private async Task SaveChanges(DbContext context, bool async)
{
if (async)
{
@@ -629,20 +1072,27 @@ private async Task SaveChanges(StoredProcedureUpdateContext context, bool async)
}
else
{
+ // ReSharper disable once MethodHasAsyncOverload
context.SaveChanges();
}
}
- protected StoredProcedureUpdateContext CreateContext()
- => Fixture.CreateContext();
-
- public static IEnumerable