From 4b9f3b3673268d5f2724174b379e083be6aa40fd Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 10 Apr 2019 13:33:11 -0700 Subject: [PATCH] Update DeleteBehavior to allow client-only cascades Issue #12661 --- .../Internal/MigrationsModelDiffer.cs | 19 +- .../Internal/InternalEntityEntry.cs | 9 +- .../ChangeTracking/Internal/StateManager.cs | 5 +- src/EFCore/DeleteBehavior.cs | 89 ++- .../GraphUpdatesInMemoryTest.cs | 144 +--- .../GraphUpdatesFixtureBase.cs | 3 +- .../GraphUpdatesTestBase.cs | 659 +++++++---------- .../GraphUpdatesSqlServerTest.cs | 670 ------------------ .../GraphUpdatesSqlServerTestBase.cs | 27 + .../GraphUpdatesSqlServerTestClientCascade.cs | 34 + ...GraphUpdatesSqlServerTestClientNoAction.cs | 33 + .../GraphUpdatesSqlServerTestIdentity.cs | 25 + .../GraphUpdatesSqlServerTestSequence.cs | 29 + 13 files changed, 551 insertions(+), 1195 deletions(-) delete mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTest.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestBase.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientCascade.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientNoAction.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestIdentity.cs create mode 100644 test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestSequence.cs diff --git a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs index 3bc656215b6..e7aa9c38d1a 100644 --- a/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -1965,11 +1965,20 @@ private ValueConverter GetValueConverter(IProperty property) => TypeMappingSource.GetMapping(property).Converter; private static ReferentialAction ToReferentialAction(DeleteBehavior deleteBehavior) - => deleteBehavior == DeleteBehavior.Cascade - ? ReferentialAction.Cascade - : deleteBehavior == DeleteBehavior.SetNull - ? ReferentialAction.SetNull - : ReferentialAction.Restrict; + { + switch (deleteBehavior) + { + case DeleteBehavior.SetNull: + return ReferentialAction.SetNull; + case DeleteBehavior.Cascade: + return ReferentialAction.Cascade; + case DeleteBehavior.NoAction: + case DeleteBehavior.ClientNoAction: + return ReferentialAction.NoAction; + default: + return ReferentialAction.Restrict; + } + } private static object[,] ToMultidimensionalArray(IReadOnlyList values) { diff --git a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs index 2bb0888bead..176540dccee 100644 --- a/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs +++ b/src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs @@ -975,7 +975,8 @@ private void SetProperty( && valueType == CurrentValueType.Normal && (!asProperty.ClrType.IsNullableType() || asProperty.GetContainingForeignKeys().Any( - fk => (fk.DeleteBehavior == DeleteBehavior.Cascade) + fk => (fk.DeleteBehavior == DeleteBehavior.Cascade + || fk.DeleteBehavior == DeleteBehavior.ClientCascade) && fk.DeclaringEntityType.IsAssignableFrom(EntityType)))) { if (value == null) @@ -1177,7 +1178,8 @@ public virtual void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool for if (_stateData.IsPropertyFlagged(property.GetIndex(), PropertyFlag.Null)) { if (properties.Any(p => p.IsNullable) - && foreignKey.DeleteBehavior != DeleteBehavior.Cascade) + && foreignKey.DeleteBehavior != DeleteBehavior.Cascade + && foreignKey.DeleteBehavior != DeleteBehavior.ClientCascade) { foreach (var toNull in properties) { @@ -1202,7 +1204,8 @@ public virtual void HandleConceptualNulls(bool sensitiveLoggingEnabled, bool for } } - var cascadeFk = fks.FirstOrDefault(fk => fk.DeleteBehavior == DeleteBehavior.Cascade); + var cascadeFk = fks.FirstOrDefault(fk => fk.DeleteBehavior == DeleteBehavior.Cascade + || fk.DeleteBehavior == DeleteBehavior.ClientCascade); if (cascadeFk != null && (force || (!isCascadeDelete diff --git a/src/EFCore/ChangeTracking/Internal/StateManager.cs b/src/EFCore/ChangeTracking/Internal/StateManager.cs index 74b9769f1a7..a25c4c7daa3 100644 --- a/src/EFCore/ChangeTracking/Internal/StateManager.cs +++ b/src/EFCore/ChangeTracking/Internal/StateManager.cs @@ -910,11 +910,12 @@ public virtual void CascadeDelete(InternalEntityEntry entry, bool force) { if (dependent.EntityState != EntityState.Deleted && dependent.EntityState != EntityState.Detached - && fk.DeleteBehavior != DeleteBehavior.Restrict + && fk.DeleteBehavior != DeleteBehavior.ClientNoAction && (dependent.EntityState == EntityState.Added || KeysEqual(entry, fk, dependent))) { - if (fk.DeleteBehavior == DeleteBehavior.Cascade + if ((fk.DeleteBehavior == DeleteBehavior.Cascade + || fk.DeleteBehavior == DeleteBehavior.ClientCascade) && doCascadeDelete) { var cascadeState = dependent.EntityState == EntityState.Added diff --git a/src/EFCore/DeleteBehavior.cs b/src/EFCore/DeleteBehavior.cs index 94f6ceb29c6..09b42d98430 100644 --- a/src/EFCore/DeleteBehavior.cs +++ b/src/EFCore/DeleteBehavior.cs @@ -18,7 +18,6 @@ namespace Microsoft.EntityFrameworkCore /// /// Note that the in-memory behavior for entities that are currently tracked by /// the can be different from the behavior that happens in the database. - /// See the behavior for more details. /// /// public enum DeleteBehavior @@ -26,17 +25,15 @@ public enum DeleteBehavior /// /// /// For entities being tracked by the , the values of foreign key properties in - /// dependent entities are set to null. This helps keep the graph of entities in a consistent - /// state while they are being tracked, such that a fully consistent graph can then be written to - /// the database. If a property cannot be set to null because it is not a nullable type, - /// then an exception will be thrown when is called. - /// This is the same as the behavior. + /// dependent entities are set to null when the related principal is deleted. + /// This helps keep the graph of entities in a consistent state while they are being tracked, such that a + /// fully consistent graph can then be written to the database. If a property cannot be set to null because + /// it is not a nullable type, then an exception will be thrown when is called. /// /// /// If the database has been created from the model using Entity Framework Migrations or the /// method, then the behavior in the database /// is to generate an error if a foreign key constraint is violated. - /// This is the same as the behavior. /// /// /// This is the default for optional relationships. That is, for relationships that have @@ -48,9 +45,10 @@ public enum DeleteBehavior /// /// /// For entities being tracked by the , the values of foreign key properties in - /// dependent entities are not changed. This can result in an inconsistent graph of entities - /// where the values of foreign key properties do not match the relationships in the - /// graph. + /// dependent entities are set to null when the related principal is deleted. + /// This helps keep the graph of entities in a consistent state while they are being tracked, such that a + /// fully consistent graph can then be written to the database. If a property cannot be set to null because + /// it is not a nullable type, then an exception will be thrown when is called. /// /// /// If the database has been created from the model using Entity Framework Migrations or the @@ -63,36 +61,89 @@ public enum DeleteBehavior /// /// /// For entities being tracked by the , the values of foreign key properties in - /// dependent entities are set to null. This helps keep the graph of entities in a consistent - /// state while they are being tracked, such that a fully consistent graph can then be written to - /// the database. If a property cannot be set to null because it is not a nullable type, - /// then an exception will be thrown when is called. + /// dependent entities are set to null when the related principal is deleted. + /// This helps keep the graph of entities in a consistent state while they are being tracked, such that a + /// fully consistent graph can then be written to the database. If a property cannot be set to null because + /// it is not a nullable type, then an exception will be thrown when is called. /// /// /// If the database has been created from the model using Entity Framework Migrations or the /// method, then the behavior in the database is /// the same as is described above for tracked entities. Keep in mind that some databases cannot easily - /// support this behavior, especially if there are cycles in relationships. + /// support this behavior, especially if there are cycles in relationships, in which case it may + /// be better to use which will allow EF to cascade null values + /// on loaded entities even if the database does not support this. /// /// SetNull, /// /// - /// For entities being tracked by the , the dependent entities - /// will also be deleted when is called. + /// For entities being tracked by the , dependent entities + /// will deleted when the related principal is deleted. /// /// /// If the database has been created from the model using Entity Framework Migrations or the /// method, then the behavior in the database is /// the same as is described above for tracked entities. Keep in mind that some databases cannot easily - /// support this behavior, especially if there are cycles in relationships. + /// support this behavior, especially if there are cycles in relationships, in which case it may + /// be better to use which will allow EF to perform cascade deletes + /// on loaded entities even if the database does not support this. /// /// /// This is the default for required relationships. That is, for relationships that have /// non-nullable foreign keys. /// /// - Cascade + Cascade, + + /// + /// + /// For entities being tracked by the , dependent entities + /// will deleted when the related principal is deleted. + /// + /// + /// If the database has been created from the model using Entity Framework Migrations or the + /// method, then the behavior in the database + /// is to generate an error if a foreign key constraint is violated. + /// + /// + ClientCascade, + + /// + /// + /// For entities being tracked by the , the values of foreign key properties in + /// dependent entities are set to null when the related principal is deleted. + /// This helps keep the graph of entities in a consistent state while they are being tracked, such that a + /// fully consistent graph can then be written to the database. If a property cannot be set to null because + /// it is not a nullable type, then an exception will be thrown when is called. + /// + /// + /// If the database has been created from the model using Entity Framework Migrations or the + /// method, then the behavior in the database + /// is to generate an error if a foreign key constraint is violated. + /// + /// + NoAction, + + + /// + /// + /// Note: it is unusual to use this value. Consider using instead to match + /// the behavior of EF6 with cascading deletes disabled. + /// + /// + /// For entities being tracked by the , the values of foreign key properties in + /// dependent entities are not changed when the related principal entity is deleted. + /// This can result in an inconsistent graph of entities where the values of foreign key properties do + /// not match the relationships in the graph. + /// + /// + /// If the database has been created from the model using Entity Framework Migrations or the + /// method, then the behavior in the database + /// is to generate an error if a foreign key constraint is violated. + /// + /// + ClientNoAction } } diff --git a/test/EFCore.InMemory.FunctionalTests/GraphUpdatesInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/GraphUpdatesInMemoryTest.cs index 047a61a4876..16c78c6fa8a 100644 --- a/test/EFCore.InMemory.FunctionalTests/GraphUpdatesInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/GraphUpdatesInMemoryTest.cs @@ -16,212 +16,140 @@ public GraphUpdatesInMemoryTest(GraphUpdatesInMemoryFixture fixture) { } - public override DbUpdateException Optional_One_to_one_relationships_are_one_to_one( + public override void Optional_One_to_one_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { // FK uniqueness not enforced in in-memory database - return null; } - public override DbUpdateException Required_One_to_one_relationships_are_one_to_one( + public override void Required_One_to_one_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { // FK uniqueness not enforced in in-memory database - return null; } - public override DbUpdateException Optional_One_to_one_with_AK_relationships_are_one_to_one( + public override void Optional_One_to_one_with_AK_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { // FK uniqueness not enforced in in-memory database - return null; } - public override DbUpdateException Required_One_to_one_with_AK_relationships_are_one_to_one( + public override void Required_One_to_one_with_AK_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { // FK uniqueness not enforced in in-memory database - return null; } - public override void Save_required_one_to_one_changed_by_reference_with_alternate_key( + public override void Save_required_one_to_one_changed_by_reference( ChangeMechanism changeMechanism, - bool useExistingEntities, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - } - - public override void Save_required_non_PK_one_to_one_changed_by_reference_with_alternate_key( - ChangeMechanism changeMechanism, - bool useExistingEntities, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - } - - public override DbUpdateException Save_required_one_to_one_changed_by_reference( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - return null; - } - - public override void Save_removed_required_many_to_one_dependents( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - } - - public override void Save_required_non_PK_one_to_one_changed_by_reference( - ChangeMechanism changeMechanism, - bool useExistingEntities, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - } - - public override void Sever_required_one_to_one_with_alternate_key( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - } - - public override DbUpdateException Sever_required_one_to_one( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database - return null; - } - - public override void Sever_required_non_PK_one_to_one( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - // Cascade delete not supported by in-memory database + // FK uniqueness not enforced in in-memory database } - public override void Sever_required_non_PK_one_to_one_with_alternate_key( + public override void Sever_required_one_to_one( ChangeMechanism changeMechanism, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_many_to_one_dependents_are_cascade_deleted_in_store( + public override void Required_many_to_one_dependents_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_one_to_one_are_cascade_deleted_in_store( + public override void Required_one_to_one_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_in_store( + public override void Required_non_PK_one_to_one_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( + public override void Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( + public override void Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( + public override void Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade delete not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Optional_many_to_one_dependents_are_orphaned_in_store( + public override void Optional_many_to_one_dependents_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Optional_one_to_one_are_orphaned_in_store( + public override void Optional_one_to_one_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( + public override void Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned_in_store( + public override void Optional_one_to_one_with_alternate_key_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( + public override void Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_one_to_one_are_cascade_detached_when_Added( + public override void Required_one_to_one_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( + public override void Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_detached_when_Added( + public override void Required_non_PK_one_to_one_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - // Cascade nulls not supported by in-memory database - return null; + // FK uniqueness not enforced in in-memory database } protected override void ExecuteWithStrategyInTransaction( diff --git a/test/EFCore.Specification.Tests/GraphUpdatesFixtureBase.cs b/test/EFCore.Specification.Tests/GraphUpdatesFixtureBase.cs index 5d9712f338f..0e9696eb75d 100644 --- a/test/EFCore.Specification.Tests/GraphUpdatesFixtureBase.cs +++ b/test/EFCore.Specification.Tests/GraphUpdatesFixtureBase.cs @@ -26,7 +26,8 @@ public abstract class GraphUpdatesFixtureBase : SharedStoreFixtureBase false; + public virtual bool ForceClientNoAction => false; + public virtual bool NoStoreCascades => false; protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { diff --git a/test/EFCore.Specification.Tests/GraphUpdatesTestBase.cs b/test/EFCore.Specification.Tests/GraphUpdatesTestBase.cs index 43148c9875d..f8282abdb77 100644 --- a/test/EFCore.Specification.Tests/GraphUpdatesTestBase.cs +++ b/test/EFCore.Specification.Tests/GraphUpdatesTestBase.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Security.Authentication.ExtendedProtection; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -34,12 +33,10 @@ public abstract partial class GraphUpdatesTestBase : IClassFixture(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -87,7 +84,8 @@ public virtual DbUpdateException New_FK_is_not_cleared_on_old_dependent_delete( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { Assert.Null(context.Set().Find(removedId)); @@ -107,8 +105,6 @@ public virtual DbUpdateException New_FK_is_not_cleared_on_old_dependent_delete( } } }); - - return updateException; } [ConditionalTheory] @@ -116,11 +112,9 @@ public virtual DbUpdateException New_FK_is_not_cleared_on_old_dependent_delete( [InlineData(CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never)] [InlineData(null)] - public virtual DbUpdateException Optional_One_to_one_relationships_are_one_to_one( + public virtual void Optional_One_to_one_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - ExecuteWithStrategyInTransaction( context => { @@ -130,10 +124,8 @@ public virtual DbUpdateException Optional_One_to_one_relationships_are_one_to_on root.OptionalSingle = new OptionalSingle1(); - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); }); - - return updateException; } [ConditionalTheory] @@ -141,11 +133,9 @@ public virtual DbUpdateException Optional_One_to_one_relationships_are_one_to_on [InlineData(CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never)] [InlineData(null)] - public virtual DbUpdateException Required_One_to_one_relationships_are_one_to_one( + public virtual void Required_One_to_one_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - ExecuteWithStrategyInTransaction( context => { @@ -155,10 +145,8 @@ public virtual DbUpdateException Required_One_to_one_relationships_are_one_to_on root.RequiredSingle = new RequiredSingle1(); - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); }); - - return updateException; } [ConditionalTheory] @@ -166,11 +154,9 @@ public virtual DbUpdateException Required_One_to_one_relationships_are_one_to_on [InlineData(CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never)] [InlineData(null)] - public virtual DbUpdateException Optional_One_to_one_with_AK_relationships_are_one_to_one( + public virtual void Optional_One_to_one_with_AK_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - ExecuteWithStrategyInTransaction( context => { @@ -180,10 +166,8 @@ public virtual DbUpdateException Optional_One_to_one_with_AK_relationships_are_o root.OptionalSingleAk = new OptionalSingleAk1(); - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); }); - - return updateException; } [ConditionalTheory] @@ -191,11 +175,9 @@ public virtual DbUpdateException Optional_One_to_one_with_AK_relationships_are_o [InlineData(CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never)] [InlineData(null)] - public virtual DbUpdateException Required_One_to_one_with_AK_relationships_are_one_to_one( + public virtual void Required_One_to_one_with_AK_relationships_are_one_to_one( CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - ExecuteWithStrategyInTransaction( context => { @@ -205,10 +187,8 @@ public virtual DbUpdateException Required_One_to_one_with_AK_relationships_are_o root.RequiredSingleAk = new RequiredSingleAk1(); - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); }); - - return updateException; } [Theory] @@ -779,7 +759,7 @@ public virtual void Save_removed_required_many_to_one_dependents( removed1.Parent = null; } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { Action testCode; @@ -832,7 +812,8 @@ public virtual void Save_removed_required_many_to_one_dependents( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var root = LoadRequiredGraph(context); @@ -1086,12 +1067,10 @@ public virtual void Save_changed_optional_one_to_one( [InlineData((int)(ChangeMechanism.Principal | ChangeMechanism.Fk), null)] [InlineData((int)(ChangeMechanism.Fk | ChangeMechanism.Dependent), null)] [InlineData((int)(ChangeMechanism.Principal | ChangeMechanism.Dependent | ChangeMechanism.Fk), null)] - public virtual DbUpdateException Save_required_one_to_one_changed_by_reference( + public virtual void Save_required_one_to_one_changed_by_reference( ChangeMechanism changeMechanism, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - // This test is a bit strange because the relationships are PK<->PK, which means // that an existing entity has to be deleted and then a new entity created that has // the same key as the existing entry. In other words it is a new incarnation of the same @@ -1126,9 +1105,9 @@ public virtual DbUpdateException Save_required_one_to_one_changed_by_reference( root.RequiredSingle = null; - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -1137,7 +1116,8 @@ public virtual DbUpdateException Save_required_one_to_one_changed_by_reference( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredGraph(context); @@ -1178,7 +1158,8 @@ public virtual DbUpdateException Save_required_one_to_one_changed_by_reference( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var loadedRoot = LoadRequiredGraph(context); @@ -1187,8 +1168,6 @@ public virtual DbUpdateException Save_required_one_to_one_changed_by_reference( AssertNavigations(loadedRoot); } }); - - return updateException; } [ConditionalTheory] @@ -1353,7 +1332,7 @@ public virtual void Save_required_non_PK_one_to_one_changed_by_reference( new1dd.MoreDerivedRootId = root.Id; } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -1409,7 +1388,8 @@ public virtual void Save_required_non_PK_one_to_one_changed_by_reference( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredNonPkGraph(context); @@ -1535,12 +1515,10 @@ public virtual void Sever_optional_one_to_one( [InlineData((int)ChangeMechanism.Principal, null)] [InlineData((int)ChangeMechanism.Dependent, null)] [InlineData((int)(ChangeMechanism.Principal | ChangeMechanism.Dependent), null)] - public virtual DbUpdateException Sever_required_one_to_one( + public virtual void Sever_required_one_to_one( ChangeMechanism changeMechanism, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - Root root = null; RequiredSingle1 old1 = null; RequiredSingle2 old2 = null; @@ -1573,9 +1551,9 @@ public virtual DbUpdateException Sever_required_one_to_one( Assert.False(context.Entry(old1).Reference(e => e.Root).IsLoaded); Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -1590,7 +1568,8 @@ public virtual DbUpdateException Sever_required_one_to_one( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var loadedRoot = LoadRequiredGraph(context); @@ -1601,8 +1580,6 @@ public virtual DbUpdateException Sever_required_one_to_one( Assert.False(context.Set().Any(e => e.Id == old2.Id)); } }); - - return updateException; } [ConditionalTheory] @@ -1650,7 +1627,7 @@ public virtual void Sever_required_non_PK_one_to_one( throw new ArgumentOutOfRangeException(nameof(changeMechanism)); } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -1687,7 +1664,8 @@ public virtual void Sever_required_non_PK_one_to_one( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredNonPkGraph(context); @@ -3122,7 +3100,7 @@ public virtual void Save_removed_required_many_to_one_dependents_with_alternate_ throw new ArgumentOutOfRangeException(nameof(changeMechanism)); } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -3161,7 +3139,8 @@ public virtual void Save_removed_required_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredAkGraph(context); @@ -3691,7 +3670,7 @@ public virtual void Save_required_one_to_one_changed_by_reference_with_alternate throw new ArgumentOutOfRangeException(nameof(changeMechanism)); } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -3739,7 +3718,8 @@ public virtual void Save_required_one_to_one_changed_by_reference_with_alternate }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredAkGraph(context); @@ -3930,7 +3910,7 @@ public virtual void Save_required_non_PK_one_to_one_changed_by_reference_with_al new1dd.MoreDerivedRootId = root.AlternateId; } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -3986,7 +3966,8 @@ public virtual void Save_required_non_PK_one_to_one_changed_by_reference_with_al }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredNonPkAkGraph(context); @@ -4155,7 +4136,7 @@ public virtual void Sever_required_one_to_one_with_alternate_key( throw new ArgumentOutOfRangeException(nameof(changeMechanism)); } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -4195,7 +4176,8 @@ public virtual void Sever_required_one_to_one_with_alternate_key( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredAkGraph(context); @@ -4255,7 +4237,7 @@ public virtual void Sever_required_non_PK_one_to_one_with_alternate_key( throw new ArgumentOutOfRangeException(nameof(changeMechanism)); } - if (Fixture.ForceRestrict + if (Fixture.ForceClientNoAction || deleteOrphansTiming == CascadeTiming.Never) { var testCode = deleteOrphansTiming == CascadeTiming.Immediate @@ -4294,7 +4276,8 @@ public virtual void Sever_required_non_PK_one_to_one_with_alternate_key( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades && deleteOrphansTiming != CascadeTiming.Never) { var loadedRoot = LoadRequiredNonPkAkGraph(context); @@ -4745,12 +4728,10 @@ public virtual void Reparent_required_non_PK_one_to_one_with_alternate_key( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_deleted( + public virtual void Required_many_to_one_dependents_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -4782,12 +4763,12 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del context.ChangeTracker.CascadeChanges(); - Assert.True(cascadeRemoved.All(e => context.Entry(e).State == (Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Deleted))); + Assert.True(cascadeRemoved.All(e => context.Entry(e).State == (Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Deleted))); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -4814,7 +4795,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredGraph(context); @@ -4826,8 +4807,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del Assert.Empty(context.Set().Where(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -4905,12 +4884,10 @@ public virtual void Required_many_to_one_dependent_leaves_can_be_deleted( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned( + public virtual void Optional_many_to_one_dependents_are_orphaned( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -4942,12 +4919,12 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned( context.ChangeTracker.CascadeChanges(); - Assert.True(orphaned.All(e => context.Entry(e).State == (Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Modified))); + Assert.True(orphaned.All(e => context.Entry(e).State == (Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Modified))); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -4970,7 +4947,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalGraph(context); @@ -4981,8 +4958,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned( Assert.Equal(orphanedIds.Count, context.Set().Count(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -5060,12 +5035,10 @@ public virtual void Optional_many_to_one_dependent_leaves_can_be_deleted( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_are_orphaned( + public virtual void Optional_one_to_one_are_orphaned( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -5093,12 +5066,12 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned( context.ChangeTracker.CascadeChanges(); - Assert.Equal(Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Modified, context.Entry(orphaned).State); + Assert.Equal(Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Modified, context.Entry(orphaned).State); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -5120,7 +5093,7 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalGraph(context); @@ -5130,8 +5103,6 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned( Assert.Equal(1, context.Set().Count(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -5204,12 +5175,10 @@ public virtual void Optional_one_to_one_leaf_can_be_deleted( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_are_cascade_deleted( + public virtual void Required_one_to_one_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -5237,12 +5206,12 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted( context.ChangeTracker.CascadeChanges(); - Assert.Equal(Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); + Assert.Equal(Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -5268,7 +5237,7 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredGraph(context); @@ -5279,8 +5248,6 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted( Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -5353,12 +5320,10 @@ public virtual void Required_one_to_one_leaf_can_be_deleted( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted( + public virtual void Required_non_PK_one_to_one_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -5386,12 +5351,12 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted( context.ChangeTracker.CascadeChanges(); - Assert.Equal(Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); + Assert.Equal(Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -5417,7 +5382,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted( }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredNonPkGraph(context); @@ -5428,8 +5393,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted( Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -5502,12 +5465,10 @@ public virtual void Required_non_PK_one_to_one_leaf_can_be_deleted( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned( + public virtual void Optional_many_to_one_dependents_with_alternate_key_are_orphaned( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -5537,14 +5498,14 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ context.ChangeTracker.CascadeChanges(); - Assert.True(orphaned.All(e => context.Entry(e).State == (Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Modified))); + Assert.True(orphaned.All(e => context.Entry(e).State == (Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Modified))); } Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -5567,7 +5528,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalAkGraph(context); @@ -5578,8 +5539,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ Assert.Equal(orphanedIds.Count, context.Set().Count(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -5593,12 +5552,10 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted( + public virtual void Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -5635,7 +5592,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ context.ChangeTracker.CascadeChanges(); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { Assert.True(cascadeRemoved.All(e => context.Entry(e).State == EntityState.Unchanged)); Assert.True(cascadeRemovedC.All(e => context.Entry(e).State == EntityState.Unchanged)); @@ -5648,9 +5605,9 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -5678,7 +5635,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredAkGraph(context); @@ -5691,8 +5648,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.Empty(context.Set().Where(e => orphanedIdCs.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -5706,12 +5661,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned( + public virtual void Optional_one_to_one_with_alternate_key_are_orphaned( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -5743,7 +5696,7 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph context.ChangeTracker.CascadeChanges(); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { Assert.Equal(EntityState.Unchanged, context.Entry(orphaned).State); Assert.Equal(EntityState.Unchanged, context.Entry(orphanedC).State); @@ -5755,9 +5708,9 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph } } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -5781,7 +5734,7 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalAkGraph(context); @@ -5792,8 +5745,6 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph Assert.Equal(1, context.Set().Count(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -5807,12 +5758,10 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted( + public virtual void Required_one_to_one_with_alternate_key_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -5844,7 +5793,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc context.ChangeTracker.CascadeChanges(); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { Assert.Equal(EntityState.Unchanged, context.Entry(orphaned).State); Assert.Equal(EntityState.Unchanged, context.Entry(orphanedC).State); @@ -5856,9 +5805,9 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc } } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -5886,7 +5835,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredAkGraph(context); @@ -5898,8 +5847,6 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.Empty(context.Set().Where(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -5913,12 +5860,10 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted( + public virtual void Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -5946,12 +5891,12 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a context.ChangeTracker.CascadeChanges(); - Assert.Equal(Fixture.ForceRestrict ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); + Assert.Equal(Fixture.ForceClientNoAction ? EntityState.Unchanged : EntityState.Deleted, context.Entry(orphaned).State); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -5977,7 +5922,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredNonPkAkGraph(context); @@ -5988,8 +5933,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -6003,12 +5946,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_deleted_in_store( + public virtual void Required_many_to_one_dependents_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -6042,9 +5983,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6066,7 +6008,8 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredGraph(context); @@ -6077,8 +6020,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del Assert.Empty(context.Set().Where(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -6092,12 +6033,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_in_store( + public virtual void Required_one_to_one_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -6128,9 +6067,10 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_in_stor context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6151,7 +6091,8 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_in_stor }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredGraph(context); @@ -6161,8 +6102,6 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_in_stor Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -6176,12 +6115,10 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_in_stor [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_in_store( + public virtual void Required_non_PK_one_to_one_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -6212,9 +6149,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6235,7 +6173,8 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredNonPkGraph(context); @@ -6245,8 +6184,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -6260,12 +6197,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( + public virtual void Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -6300,9 +6235,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6325,7 +6261,8 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredAkGraph(context); @@ -6337,8 +6274,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.Empty(context.Set().Where(e => orphanedIdCs.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -6352,12 +6287,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( + public virtual void Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -6390,9 +6323,10 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6414,7 +6348,8 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredAkGraph(context); @@ -6425,8 +6360,6 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.Empty(context.Set().Where(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -6440,12 +6373,10 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( + public virtual void Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -6476,9 +6407,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction + || Fixture.NoStoreCascades) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6499,7 +6431,8 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction + && !Fixture.NoStoreCascades) { var root = LoadRequiredNonPkAkGraph(context); @@ -6509,8 +6442,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -6524,12 +6455,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_in_store( + public virtual void Optional_many_to_one_dependents_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -6563,9 +6492,9 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_in context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6590,7 +6519,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_in }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalGraph(context); @@ -6604,8 +6533,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_in Assert.True(orphaned.All(e => e.ParentId == null)); } }); - - return updateException; } [ConditionalTheory] @@ -6619,12 +6546,10 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_in [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_are_orphaned_in_store( + public virtual void Optional_one_to_one_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -6655,9 +6580,9 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_in_store( context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6678,7 +6603,7 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_in_store( }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalGraph(context); @@ -6688,8 +6613,6 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_in_store( Assert.Null(context.Set().Single(e => e.Id == orphanedId).BackId); } }); - - return updateException; } [ConditionalTheory] @@ -6703,12 +6626,10 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_in_store( [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( + public virtual void Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -6748,9 +6669,9 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6779,7 +6700,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalAkGraph(context); @@ -6797,8 +6718,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ Assert.True(orphanedC.All(e => e.ParentId == null)); } }); - - return updateException; } [ConditionalTheory] @@ -6812,12 +6731,10 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned_in_store( + public virtual void Optional_one_to_one_with_alternate_key_are_orphaned_in_store( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -6854,9 +6771,9 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph context.ChangeTracker.CascadeChanges(); } - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -6878,7 +6795,7 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { var root = LoadOptionalAkGraph(context); @@ -6889,8 +6806,6 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph Assert.Null(context.Set().Single(e => e.Id == orphanedIdC).BackId); } }); - - return updateException; } [ConditionalTheory] @@ -6904,12 +6819,10 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_deleted_starting_detached( + public virtual void Required_many_to_one_dependents_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; Root root = null; @@ -6947,7 +6860,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -6955,9 +6868,9 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -6978,7 +6891,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { root = LoadRequiredGraph(context); @@ -6990,8 +6903,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del Assert.Empty(context.Set().Where(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -7005,12 +6916,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_del [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_starting_detached( + public virtual void Optional_many_to_one_dependents_are_orphaned_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; Root root = null; @@ -7048,16 +6957,16 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_st var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Modified : EntityState.Unchanged; Assert.True(orphaned.All(e => context.Entry(e).State == expectedState)); Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -7074,7 +6983,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_st }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { root = LoadOptionalGraph(context); @@ -7085,8 +6994,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_st Assert.Equal(orphanedIds.Count, context.Set().Count(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -7100,12 +7007,10 @@ public virtual DbUpdateException Optional_many_to_one_dependents_are_orphaned_st [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detached( + public virtual void Optional_one_to_one_are_orphaned_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; Root root = null; @@ -7136,7 +7041,7 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detac var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Modified : EntityState.Unchanged; @@ -7144,9 +7049,9 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detac Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -7163,7 +7068,7 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detac }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { root = LoadOptionalGraph(context); @@ -7173,8 +7078,6 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detac Assert.Equal(1, context.Set().Count(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -7188,12 +7091,10 @@ public virtual DbUpdateException Optional_one_to_one_are_orphaned_starting_detac [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_starting_detached( + public virtual void Required_one_to_one_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; Root root = null; @@ -7224,7 +7125,7 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_startin var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -7232,9 +7133,9 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_startin Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7256,7 +7157,7 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_startin context => root = LoadRequiredGraph(context), context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { Assert.Null(root.RequiredSingle); @@ -7265,8 +7166,6 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_startin Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -7280,12 +7179,10 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_deleted_startin [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_starting_detached( + public virtual void Required_non_PK_one_to_one_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; Root root = null; @@ -7316,7 +7213,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -7324,9 +7221,9 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7347,7 +7244,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { root = LoadRequiredNonPkGraph(context); @@ -7358,8 +7255,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -7373,12 +7268,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned_starting_detached( + public virtual void Optional_many_to_one_dependents_with_alternate_key_are_orphaned_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -7421,7 +7314,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Modified : EntityState.Unchanged; @@ -7430,9 +7323,9 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -7450,7 +7343,7 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { root = LoadOptionalAkGraph(context); @@ -7462,8 +7355,6 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ Assert.Equal(orphanedIdCs.Count, context.Set().Count(e => orphanedIdCs.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -7477,12 +7368,10 @@ public virtual DbUpdateException Optional_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_starting_detached( + public virtual void Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -7524,7 +7413,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -7533,9 +7422,9 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7557,7 +7446,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { root = LoadRequiredAkGraph(context); @@ -7570,8 +7459,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.Empty(context.Set().Where(e => orphanedIdCs.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -7585,12 +7472,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned_starting_detached( + public virtual void Optional_one_to_one_with_alternate_key_are_orphaned_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -7625,7 +7510,7 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Modified : EntityState.Unchanged; @@ -7634,9 +7519,9 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else { @@ -7654,7 +7539,7 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph }, context => { - if (!Fixture.ForceRestrict) + if (!Fixture.ForceClientNoAction) { root = LoadOptionalAkGraph(context); @@ -7665,8 +7550,6 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph Assert.Equal(1, context.Set().Count(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -7680,12 +7563,10 @@ public virtual DbUpdateException Optional_one_to_one_with_alternate_key_are_orph [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( + public virtual void Required_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -7720,7 +7601,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -7729,9 +7610,9 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7753,7 +7634,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { root = LoadRequiredAkGraph(context); @@ -7765,8 +7646,6 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.Empty(context.Set().Where(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -7780,12 +7659,10 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( + public virtual void Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; Root root = null; @@ -7816,7 +7693,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Deleted : EntityState.Unchanged; @@ -7824,9 +7701,9 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7847,7 +7724,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { root = LoadRequiredNonPkAkGraph(context); @@ -7858,8 +7735,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -7873,12 +7748,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_detached_when_Added( + public virtual void Required_many_to_one_dependents_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; @@ -7926,7 +7799,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_det if ((cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict) + && !Fixture.ForceClientNoAction) { Assert.Equal(EntityState.Detached, context.Entry(added).State); Assert.True(cascadeRemoved.All(e => context.Entry(e).State == EntityState.Deleted)); @@ -7939,9 +7812,9 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_det Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -7963,7 +7836,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_det }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredGraph(context); @@ -7975,8 +7848,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_det Assert.Empty(context.Set().Where(e => orphanedIds.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -7990,12 +7861,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_are_cascade_det [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_Added( + public virtual void Required_one_to_one_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -8011,9 +7880,16 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A removedId = removed.Id; var orphaned = removed.Single; - orphanedId = orphaned.Id; - context.Entry(orphaned).State = EntityState.Added; + // Since we're pretending this isn't in the database, make it really not in the database + context.Entry(orphaned).State = EntityState.Deleted; + context.SaveChanges(); + + Assert.Equal(EntityState.Detached, context.Entry(orphaned).State); + + removed.Single = orphaned; + context.ChangeTracker.DetectChanges(); + orphanedId = orphaned.Id; Assert.Equal(EntityState.Unchanged, context.Entry(removed).State); Assert.Equal(EntityState.Added, context.Entry(orphaned).State); @@ -8031,7 +7907,7 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Detached : EntityState.Added; @@ -8039,9 +7915,9 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -8062,7 +7938,7 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredGraph(context); @@ -8073,8 +7949,6 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -8088,12 +7962,10 @@ public virtual DbUpdateException Required_one_to_one_are_cascade_detached_when_A [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached_when_Added( + public virtual void Required_non_PK_one_to_one_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -8109,9 +7981,17 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached removedId = removed.Id; var orphaned = removed.Single; - orphanedId = orphaned.Id; + // Since we're pretending this isn't in the database, make it really not in the database + context.Entry(orphaned).State = EntityState.Deleted; + context.SaveChanges(); + + Assert.Equal(EntityState.Detached, context.Entry(orphaned).State); + + removed.Single = orphaned; + context.ChangeTracker.DetectChanges(); context.Entry(orphaned).State = EntityState.Added; + orphanedId = orphaned.Id; Assert.Equal(EntityState.Unchanged, context.Entry(removed).State); Assert.Equal(EntityState.Added, context.Entry(orphaned).State); @@ -8129,7 +8009,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Detached : EntityState.Added; @@ -8137,9 +8017,9 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -8160,7 +8040,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredNonPkGraph(context); @@ -8171,8 +8051,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] @@ -8186,12 +8064,10 @@ public virtual DbUpdateException Required_non_PK_one_to_one_are_cascade_detached [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_detached_when_Added( + public virtual void Required_many_to_one_dependents_with_alternate_key_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; List orphanedIds = null; List orphanedIdCs = null; @@ -8249,7 +8125,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ if ((cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict) + && !Fixture.ForceClientNoAction) { Assert.Equal(EntityState.Detached, context.Entry(added).State); Assert.Equal(EntityState.Detached, context.Entry(addedC).State); @@ -8266,9 +8142,9 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -8292,7 +8168,7 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredAkGraph(context); @@ -8305,8 +8181,6 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ Assert.Empty(context.Set().Where(e => orphanedIdCs.Contains(e.Id))); } }); - - return updateException; } [ConditionalTheory] @@ -8320,12 +8194,10 @@ public virtual DbUpdateException Required_many_to_one_dependents_with_alternate_ [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( + public virtual void Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; var orphanedIdC = 0; @@ -8339,15 +8211,26 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc var root = LoadRequiredAkGraph(context); var removed = root.RequiredSingleAk; - removedId = removed.Id; + var orphaned = removed.Single; var orphanedC = removed.SingleComposite; - orphanedId = orphaned.Id; - orphanedIdC = orphanedC.Id; + // Since we're pretending these aren't in the database, make them really not in the database + context.Entry(orphaned).State = EntityState.Deleted; + context.Entry(orphanedC).State = EntityState.Deleted; + context.SaveChanges(); + + Assert.Equal(EntityState.Detached, context.Entry(orphaned).State); + Assert.Equal(EntityState.Detached, context.Entry(orphanedC).State); + + removed.Single = orphaned; + removed.SingleComposite = orphanedC; + context.ChangeTracker.DetectChanges(); context.Entry(orphaned).State = EntityState.Added; context.Entry(orphanedC).State = EntityState.Added; + orphanedId = orphaned.Id; + orphanedIdC = orphanedC.Id; Assert.Equal(EntityState.Unchanged, context.Entry(removed).State); Assert.Equal(EntityState.Added, context.Entry(orphaned).State); @@ -8367,7 +8250,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Detached : EntityState.Added; @@ -8376,9 +8259,9 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -8400,7 +8283,7 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredAkGraph(context); @@ -8412,8 +8295,6 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc Assert.Empty(context.Set().Where(e => e.Id == orphanedIdC)); } }); - - return updateException; } [ConditionalTheory] @@ -8427,12 +8308,10 @@ public virtual DbUpdateException Required_one_to_one_with_alternate_key_are_casc [InlineData(CascadeTiming.Never, CascadeTiming.Immediate)] [InlineData(CascadeTiming.Never, CascadeTiming.Never)] [InlineData(null, null)] - public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( + public virtual void Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( CascadeTiming? cascadeDeleteTiming, CascadeTiming? deleteOrphansTiming) { - DbUpdateException updateException = null; - var removedId = 0; var orphanedId = 0; @@ -8448,9 +8327,17 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a removedId = removed.Id; var orphaned = removed.Single; - orphanedId = orphaned.Id; + // Since we're pretending this isn't in the database, make it really not in the database + context.Entry(orphaned).State = EntityState.Deleted; + context.SaveChanges(); + + Assert.Equal(EntityState.Detached, context.Entry(orphaned).State); + + removed.Single = orphaned; + context.ChangeTracker.DetectChanges(); context.Entry(orphaned).State = EntityState.Added; + orphanedId = orphaned.Id; Assert.Equal(EntityState.Unchanged, context.Entry(removed).State); Assert.Equal(EntityState.Added, context.Entry(orphaned).State); @@ -8468,7 +8355,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a var expectedState = (cascadeDeleteTiming == CascadeTiming.Immediate || cascadeDeleteTiming == null) - && !Fixture.ForceRestrict + && !Fixture.ForceClientNoAction ? EntityState.Detached : EntityState.Added; @@ -8476,9 +8363,9 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.True(context.ChangeTracker.HasChanges()); - if (Fixture.ForceRestrict) + if (Fixture.ForceClientNoAction) { - updateException = Assert.Throws(() => context.SaveChanges()); + Assert.Throws(() => context.SaveChanges()); } else if (cascadeDeleteTiming == CascadeTiming.Never) { @@ -8499,7 +8386,7 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a }, context => { - if (!Fixture.ForceRestrict + if (!Fixture.ForceClientNoAction && cascadeDeleteTiming != CascadeTiming.Never) { var root = LoadRequiredNonPkAkGraph(context); @@ -8510,8 +8397,6 @@ public virtual DbUpdateException Required_non_PK_one_to_one_with_alternate_key_a Assert.Empty(context.Set().Where(e => e.Id == orphanedId)); } }); - - return updateException; } [ConditionalTheory] diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTest.cs deleted file mode 100644 index daf2f9bc442..00000000000 --- a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTest.cs +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.TestUtilities; - -namespace Microsoft.EntityFrameworkCore -{ - public abstract class GraphUpdatesSqlServerTest - { - public abstract class GraphUpdatesSqlServerTestBase : GraphUpdatesTestBase - where TFixture : GraphUpdatesSqlServerTestBase.GraphUpdatesSqlServerFixtureBase, new() - { - protected GraphUpdatesSqlServerTestBase(TFixture fixture) - : base(fixture) - { - } - - protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - => facade.UseTransaction(transaction.GetDbTransaction()); - - public abstract class GraphUpdatesSqlServerFixtureBase : GraphUpdatesFixtureBase - { - public TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)ListLoggerFactory; - protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; - } - } - - public class Identity : GraphUpdatesSqlServerTestBase - { - public Identity(GraphUpdatesWithIdentitySqlServerFixture fixture) - : base(fixture) - { - } - - public class GraphUpdatesWithIdentitySqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphIdentityUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.ForSqlServerUseIdentityColumns(); - - base.OnModelCreating(modelBuilder, context); - } - } - } - - public class Restrict : GraphUpdatesSqlServerTestBase - { - public Restrict(GraphUpdatesWithRestrictSqlServerFixture fixture) - : base(fixture) - { - } - - public override DbUpdateException Optional_One_to_one_relationships_are_one_to_one( - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_One_to_one_relationships_are_one_to_one(deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("IX_OptionalSingle1_RootId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_One_to_one_relationships_are_one_to_one( - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_One_to_one_relationships_are_one_to_one(deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("PK_RequiredSingle1", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_One_to_one_with_AK_relationships_are_one_to_one( - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_One_to_one_with_AK_relationships_are_one_to_one(deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("IX_OptionalSingleAk1_RootId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_One_to_one_with_AK_relationships_are_one_to_one( - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_One_to_one_with_AK_relationships_are_one_to_one(deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("IX_RequiredSingleAk1_RootId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Save_required_one_to_one_changed_by_reference( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Save_required_one_to_one_changed_by_reference(changeMechanism, deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Sever_required_one_to_one( - ChangeMechanism changeMechanism, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Sever_required_one_to_one(changeMechanism, deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Required2_Required1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_are_orphaned( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_are_orphaned( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Optional2_Optional1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_are_orphaned( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_are_orphaned( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingle2_OptionalSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingle2_RequiredNonPkSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_with_alternate_key_are_orphaned( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalAk2_OptionalAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredAk2_RequiredAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_with_alternate_key_are_orphaned( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingleAk2_OptionalSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_with_alternate_key_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingleAk2_RequiredSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingleAk2_RequiredNonPkSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Required2_Required1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingle2_RequiredNonPkSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredAk2_RequiredAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_with_alternate_key_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingleAk2_RequiredSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingleAk2_RequiredNonPkSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_are_orphaned_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_are_orphaned_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Optional2_Optional1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_are_orphaned_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_are_orphaned_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingle2_OptionalSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_with_alternate_key_are_orphaned_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalAk2_OptionalAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned_in_store( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_with_alternate_key_are_orphaned_in_store( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingleAk2_OptionalSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Required2_Required1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_are_orphaned_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_are_orphaned_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Optional2_Optional1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_are_orphaned_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_are_orphaned_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingle2_OptionalSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingle2_RequiredNonPkSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_many_to_one_dependents_with_alternate_key_are_orphaned_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_many_to_one_dependents_with_alternate_key_are_orphaned_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalAk2_OptionalAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_with_alternate_key_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredAk2_RequiredAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Optional_one_to_one_with_alternate_key_are_orphaned_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Optional_one_to_one_with_alternate_key_are_orphaned_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_OptionalSingleAk2_OptionalSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingleAk2_RequiredSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_with_alternate_key_are_cascade_deleted_starting_detached( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingleAk2_RequiredNonPkSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_Required2_Required1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingle2_RequiredSingle1_Id", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingle2_RequiredNonPkSingle1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_many_to_one_dependents_with_alternate_key_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_many_to_one_dependents_with_alternate_key_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredAk2_RequiredAk1_ParentId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_one_to_one_with_alternate_key_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredSingleAk2_RequiredSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public override DbUpdateException Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( - CascadeTiming? cascadeDeleteTiming, - CascadeTiming? deleteOrphansTiming) - { - var updateException = base.Required_non_PK_one_to_one_with_alternate_key_are_cascade_detached_when_Added( - cascadeDeleteTiming, - deleteOrphansTiming); - - // Disabled check -- see issue #11031 - //Assert.Contains("FK_RequiredNonPkSingleAk2_RequiredNonPkSingleAk1_BackId", updateException.InnerException.Message); - - return updateException; - } - - public class GraphUpdatesWithRestrictSqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphRestrictUpdatesTest"; - public override bool ForceRestrict => true; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - base.OnModelCreating(modelBuilder, context); - - foreach (var foreignKey in modelBuilder.Model - .GetEntityTypes() - .SelectMany(e => e.GetDeclaredForeignKeys())) - { - foreignKey.DeleteBehavior = DeleteBehavior.Restrict; - } - } - } - } - - [SqlServerCondition(SqlServerCondition.SupportsSequences)] - public class Sequence : GraphUpdatesSqlServerTestBase - { - public Sequence(GraphUpdatesWithSequenceSqlServerFixture fixture) - : base(fixture) - { - } - - public class GraphUpdatesWithSequenceSqlServerFixture : GraphUpdatesSqlServerFixtureBase - { - protected override string StoreName { get; } = "GraphSequenceUpdatesTest"; - - protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) - { - modelBuilder.ForSqlServerUseSequenceHiLo(); // ensure model uses sequences - base.OnModelCreating(modelBuilder, context); - } - } - } - } -} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestBase.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestBase.cs new file mode 100644 index 00000000000..70249b9f897 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestBase.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace Microsoft.EntityFrameworkCore +{ + public abstract class GraphUpdatesSqlServerTestBase : GraphUpdatesTestBase + where TFixture : GraphUpdatesSqlServerTestBase.GraphUpdatesSqlServerFixtureBase, new() + { + protected GraphUpdatesSqlServerTestBase(TFixture fixture) + : base(fixture) + { + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public abstract class GraphUpdatesSqlServerFixtureBase : GraphUpdatesFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory => (TestSqlLoggerFactory)ListLoggerFactory; + protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientCascade.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientCascade.cs new file mode 100644 index 00000000000..edd712e7326 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientCascade.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerTestClientCascade : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerTestClientCascade(GraphUpdatesWithClientCascadeSqlServerFixture fixture) + : base(fixture) + { + } + + public class GraphUpdatesWithClientCascadeSqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphClientCascadeUpdatesTest"; + public override bool NoStoreCascades => true; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + foreach (var foreignKey in modelBuilder.Model + .GetEntityTypes() + .SelectMany(e => MutableEntityTypeExtensions.GetDeclaredForeignKeys(e)) + .Where(e => e.DeleteBehavior == DeleteBehavior.Cascade)) + { + foreignKey.DeleteBehavior = DeleteBehavior.ClientCascade; + } + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientNoAction.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientNoAction.cs new file mode 100644 index 00000000000..8b2bebbdced --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestClientNoAction.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Linq; + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerTestClientNoAction : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerTestClientNoAction(GraphUpdatesWithClientNoActionSqlServerFixture fixture) + : base(fixture) + { + } + + public class GraphUpdatesWithClientNoActionSqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphClientNoActionUpdatesTest"; + public override bool ForceClientNoAction => true; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + foreach (var foreignKey in modelBuilder.Model + .GetEntityTypes() + .SelectMany(e => MutableEntityTypeExtensions.GetDeclaredForeignKeys(e))) + { + foreignKey.DeleteBehavior = DeleteBehavior.ClientNoAction; + } + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestIdentity.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestIdentity.cs new file mode 100644 index 00000000000..bfc12cb4833 --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestIdentity.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.EntityFrameworkCore +{ + public class GraphUpdatesSqlServerTestIdentity : GraphUpdatesSqlServerTestBase + { + public GraphUpdatesSqlServerTestIdentity(GraphUpdatesWithIdentitySqlServerFixture fixture) + : base(fixture) + { + } + + public class GraphUpdatesWithIdentitySqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphIdentityUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.ForSqlServerUseIdentityColumns(); + + base.OnModelCreating(modelBuilder, context); + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestSequence.cs b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestSequence.cs new file mode 100644 index 00000000000..0e0e821cf4c --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/GraphUpdatesSqlServerTestSequence.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace Microsoft.EntityFrameworkCore +{ + [SqlServerCondition(SqlServerCondition.SupportsSequences)] + public class GraphUpdatesSqlServerTestSequence : GraphUpdatesSqlServerTestBase< + GraphUpdatesSqlServerTestSequence.GraphUpdatesWithSequenceSqlServerFixture> + { + public GraphUpdatesSqlServerTestSequence(GraphUpdatesWithSequenceSqlServerFixture fixture) + : base(fixture) + { + } + + public class GraphUpdatesWithSequenceSqlServerFixture : GraphUpdatesSqlServerFixtureBase + { + protected override string StoreName { get; } = "GraphSequenceUpdatesTest"; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.ForSqlServerUseSequenceHiLo(); // ensure model uses sequences + base.OnModelCreating(modelBuilder, context); + } + } + } +}