diff --git a/global.json b/global.json index a6431c20..536fc47a 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.409", + "version": "8.0.119", "rollForward": "latestMinor" }, "msbuild-sdks": { diff --git a/src/FunctionalTest/Smo/ScriptingTests/ScripterTests.cs b/src/FunctionalTest/Smo/ScriptingTests/ScripterTests.cs index e8e8bc55..31dc1be6 100644 --- a/src/FunctionalTest/Smo/ScriptingTests/ScripterTests.cs +++ b/src/FunctionalTest/Smo/ScriptingTests/ScripterTests.cs @@ -107,5 +107,52 @@ public void Script_Script_ForCreateOrAlter_fails_pre_sql2016() Assert.That(urnErrors, Is.EquivalentTo(new Urn[] { sp.Urn }), "CreateOrAlter should have errors when scripting pre-sql2016"); }); } + + [TestMethod] + [SupportedServerVersionRange(DatabaseEngineType = Management.Common.DatabaseEngineType.Standalone)] + [SupportedServerVersionRange(DatabaseEngineType = Management.Common.DatabaseEngineType.SqlAzureDatabase)] + [UnsupportedDatabaseEngineEdition(DatabaseEngineEdition.SqlOnDemand)] + [UnsupportedFeature(SqlFeature.Fabric)] + public void Scripter_MultipleScriptCallsWithDrops_ShouldNotFailWithObjectDroppedException() + { + // Regression test for issue: "Cannot access properties or methods for the Microsoft.SqlServer.Management.Smo.Table '[dbo].[MyTable]', because it has been dropped." + // When calling script operations multiple times with ScriptDrops=true, subsequent calls should not fail + // The fix ensures that objects are only marked as dropped during actual execution (ForDirectExecution=true), not during script generation + ExecuteFromDbPool(db => + { + var table = db.CreateTable("test_table_multiple_script_calls"); + var scripter = new Scripter(db.Parent); + + scripter.Options.IncludeDatabaseContext = true; + scripter.Options.ScriptSchema = true; + scripter.Options.ScriptData = false; + + // First scripting call - this should work + scripter.Options.ScriptDrops = true; + scripter.Options.IncludeIfNotExists = true; + var dropScript1 = scripter.EnumScript(new[] { table.Urn }).ToArray(); + Assert.That(dropScript1.Length, Is.GreaterThan(0), "First drop script should be generated"); + + scripter.Options.ScriptDrops = false; + scripter.Options.IncludeIfNotExists = false; + var createScript1 = scripter.EnumScript(new[] { table.Urn }).ToArray(); + Assert.That(createScript1.Length, Is.GreaterThan(0), "First create script should be generated"); + + // Second scripting call - this should not fail with "object has been dropped" error + scripter.Options.ScriptDrops = true; + scripter.Options.IncludeIfNotExists = true; + var dropScript2 = scripter.EnumScript(new[] { table.Urn }).ToArray(); + Assert.That(dropScript2.Length, Is.GreaterThan(0), "Second drop script should be generated without error"); + + scripter.Options.ScriptDrops = false; + scripter.Options.IncludeIfNotExists = false; + var createScript2 = scripter.EnumScript(new[] { table.Urn }).ToArray(); + Assert.That(createScript2.Length, Is.GreaterThan(0), "Second create script should be generated without error"); + + // Verify the scripts are equivalent + Assert.That(dropScript2, Is.EqualTo(dropScript1), "Drop scripts should be identical"); + Assert.That(createScript2, Is.EqualTo(createScript1), "Create scripts should be identical"); + }); + } } } diff --git a/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs b/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs index 48efde72..a57416c8 100644 --- a/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs +++ b/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs @@ -2976,8 +2976,9 @@ protected void DropImplWorker(ref Urn urn, bool isDropIfExists = false) parentColl.RemoveObject(this.key); } - // update object state to only if we are in execution mode - if (!this.ExecutionManager.Recording) + // update object state only if we are in execution mode, not just scripting + // Use ForDirectExecution to distinguish between actual drops vs script generation + if (sp.ForDirectExecution) { // mark the object as being dropped this.MarkDropped();