如何用C# SMO复现SSMS的‘脚本表为→删除并创建’操作?
使用Microsoft.SqlServer.Management.Smo复现SSMS“删除并创建”脚本效果
一、优化ScriptingOptions配置
你的现有配置缺少几个关键属性,调整后可以让Smo生成更贴近SSMS的输出:
var scriptingOptions = new ScriptingOptions { EnforceScriptingOptions = true, IncludeDatabaseContext = true, // 生成USE <数据库名>语句 AllowSystemObjects = false, SchemaQualify = true, // 带完整架构名 DriAllConstraints = true, // 包含所有DRI约束(主键、外键等) Indexes = true, // 生成索引脚本 DriDefaults = true, // 生成默认值约束 NoCollation = true, ScriptDrops = true, // 生成删除对象的脚本(核心:对应SSMS的"删除并创建") AnsiNulls = true, // 生成SET ANSI_NULLS ON QuotedIdentifier = true, // 生成SET QUOTED_IDENTIFIER ON IncludeHeaders = true, // 生成类似/****** Object: ... ******/的注释头 BatchSeparator = "GO", // 用GO作为批处理分隔符 ScriptBatchTerminator = true // 在每个批处理末尾添加GO };
二、补充缺失的约束删除逻辑
Smo默认生成的删除表脚本不会先删除关联的约束(比如外键、检查约束),需要手动遍历表的约束并生成DROP语句:
// 假设table是你的Smo.Table对象 var dropConstraintScripts = new List<string>(); // 生成外键约束删除脚本 foreach (ForeignKey fk in table.ForeignKeys) { dropConstraintScripts.Add($"ALTER TABLE {table.Schema}.{table.Name} DROP CONSTRAINT {fk.Name};"); } // 生成检查约束删除脚本 foreach (CheckConstraint ck in table.CheckConstraints) { dropConstraintScripts.Add($"ALTER TABLE {table.Schema}.{table.Name} DROP CONSTRAINT {ck.Name};"); } // 生成默认值约束删除脚本 foreach (DefaultConstraint df in table.DefaultConstraints) { dropConstraintScripts.Add($"ALTER TABLE {table.Schema}.{table.Name} DROP CONSTRAINT {df.Name};"); }
三、整合完整脚本流程
将手动生成的约束删除脚本、Smo生成的删除表脚本、创建表脚本整合:
// 1. 获取USE语句(IncludeDatabaseContext=true时Smo会自动生成,也可手动拼接) var useDatabaseScript = $"USE [{table.Parent.Name}];"; // 2. 约束删除脚本(按批处理分隔) var dropConstraints = string.Join("\nGO\n", dropConstraintScripts); // 3. 获取Smo生成的删除+创建表脚本 var tableScripts = table.Script(scriptingOptions); // 4. 整合所有部分并输出 var fullScript = new List<string> { useDatabaseScript, dropConstraints, string.Join("\n", tableScripts) }; Console.WriteLine(string.Join("\nGO\n", fullScript));
四、其他对象(视图、函数、存储过程)的处理
对于视图、函数、存储过程,使用类似的配置即可生成"删除并创建"脚本,核心是保持ScriptDrops = true:
视图示例
var viewScriptingOptions = new ScriptingOptions { ScriptDrops = true, SchemaQualify = true, IncludeHeaders = true, BatchSeparator = "GO", ScriptBatchTerminator = true }; var viewScripts = view.Script(viewScriptingOptions);
存储过程/函数示例
var procScriptingOptions = new ScriptingOptions { ScriptDrops = true, SchemaQualify = true, IncludeHeaders = true, BatchSeparator = "GO", ScriptBatchTerminator = true, ScriptBody = true // 确保生成完整的过程/函数体 }; var procScripts = storedProcedure.Script(procScriptingOptions);
关键细节调整
如果需要完全匹配SSMS的IF EXISTS判断逻辑,可以手动替换Smo生成的DROP语句,比如将:
DROP TABLE [dbo].[Table]
替换为:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Table]') AND type in (N'U')) DROP TABLE [dbo].[Table]
内容的提问来源于stack exchange,提问作者joeschmoe54321
相关产品推荐
相关产品推荐

