无法让EnumScript()生成约束

时间:2013-09-24 22:03:28

标签: sql-server ssms smo

我正在尝试以编程方式获取我可以使用任务>从SSMS手动获取的内容。生成脚本

下面的代码工作正常,除了它不会产生任何约束。我没有得到任何ALTER TABLE [foo] ADD CONSTRAINT ... ON DELETE CASCADE等等。我已经尝试了很多Dri选项的组合以及不同的数据库。我很难过。

感谢您的见解!

        Scripter scrp = new Scripter(srv)
        {
            Options =
            {
                ScriptDrops = false,
                WithDependencies = false,
                Indexes = true,
                Triggers = false,
                Default = true,
                DriAll = true,
                //ScriptData = true,
                ScriptSchema = true,
            }
        };

        var urns = new List<Urn>();

        foreach (Table tb in db.Tables)
        {
            if (tb.IsSystemObject == false)
            {
                urns.Add(tb.Urn);
            }
        }

        var inserts = scrp.EnumScript(urns.ToArray());
        File.WriteAllLines(path, inserts);

1 个答案:

答案 0 :(得分:1)

好吧,我找到了一个解决方案,即使用每个对象的Script方法生成模式,使用EnumScript方法(使用scriptSchema=false)生成插入表格内容。

        foreach (Table tb in db.Tables)
        {
            if (tb.IsSystemObject == false)
            {
                foreach (var s in tb.Script(schemaOptions))
                    strings.Add(s);

                if (scriptData)
                {
                    foreach (var i in tb.EnumScript(insertOptions))
                        strings.Add(i);
                }
            }
        }

我承认这个解决方案感觉有点空洞,因为我从未发现为什么原始方法不起作用。这是一个没有诊断的修复,但仍然是修复。

至于为什么我首先写这个东西,我的数据库在共享服务器上,并且没有任何方法可以获得我可以脱机或在其他地方使用的自动备份。所以这是我的备份计划。

上面的解决方案遵循Microsoft提供的代码示例:Scripting。这种方法的问题是表格是以No Particular Order编写的,但需要按照它们的依赖关系顺序排列,以便定义约束并插入行。无法在尚不存在的表中引用外键。

我到目前为止最好的解决方案是使用DependencyWalker.DiscoverDependencies()来获得 依赖树,DependencyWalker.WalkDependencies()获取一个线性列表并迭代该列表,如下所示:

        var urns = new List<Urn>();
        Scripter schemaScripter = new Scripter(srv) { Options = schemaOptions };
        Scripter insertScripter = new Scripter(srv) { Options = insertOptions };
        var dw = new DependencyWalker(srv);

        foreach (Table t in db.Tables)
            if (t.IsSystemObject == false)
                urns.Add(t.Urn);
        DependencyTree dTree = dw.DiscoverDependencies(urns.ToArray(), true);
        DependencyCollection dColl = dw.WalkDependencies(dTree);

        foreach (var d in dColl)
        {
            foreach (var s in schemaScripter.Script(new Urn[] { d.Urn }))
                strings.Add(s);
            strings.Add("GO");
            if (scriptData)
            {
                int n = 0;
                foreach (var i in insertScripter.EnumScript(new Urn[] {d.Urn}))
                {
                    strings.Add(i);
                    if ((++n) % 100 == 0)
                        strings.Add("GO");
                }
            }
        }
        ...
        File.WriteAllLines(path, strings);

经常添加“GO”会使批量大小变小,因此SSMS不会耗尽内存。

要完成该示例,数据库将编写脚本:

        foreach (var s in db.Script(new ScriptingOptions { ScriptSchema = true }))
            strings.Add(s);
        strings.Add("GO");
        strings.Add("use " + dbName);
        strings.Add("GO");

用户,视图和存储过程因此编写脚本:

        foreach (User u in db.Users)
        {
            if (u.IsSystemObject == false)
            {
                foreach (var s in u.Script(new ScriptingOptions { ScriptSchema = true }))
                    strings.Add(s);
            }
        }

此代码生成的文件可用于重新创建数据库。我把它放在一台旧笔记本电脑上,每小时为我的在线数据库提取快照。穷人的日志传送/备份/镜像。