Sql server can';t获取EnumScript()以生成约束

Sql server can';t获取EnumScript()以生成约束,sql-server,ssms,smo,Sql Server,Ssms,Smo,我正试图通过使用任务>生成脚本,以编程方式从SSM手动获取所需内容 下面的代码运行良好,只是没有生成任何约束。我没有得到任何altertable[foo]添加约束。。。在DELETE CASCADE等方面,我尝试了许多组合的Dri选项以及不同的数据库。我被难住了 谢谢你的洞察力 Scripter scrp = new Scripter(srv) { Options = { Script

我正试图通过使用任务>生成脚本,以编程方式从SSM手动获取所需内容

下面的代码运行良好,只是没有生成任何约束。我没有得到任何
altertable[foo]添加约束。。。在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);
Scripter-scrp=新脚本编写器(srv)
{
选择权=
{
ScriptDrops=false,
WithDependencies=false,
索引=真,
触发器=false,
默认值=真,
DriAll=真,
//ScriptData=true,
ScriptSchema=true,
}
};
var urns=新列表();
foreach(数据库表中的表tb)
{
if(tb.IsSystemObject==false)
{
urns.Add(tb.Urn);
}
}
var inserts=scrp.EnumScript(urns.ToArray());
File.writeAllines(路径、插入);

好吧,我找到了一个解决方案,那就是使用每个对象的
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在此给出的代码示例:。这种方法的问题是,表没有特定的顺序编写脚本,但需要按照其依赖关系的顺序编写,以便定义约束和插入行。无法在尚不存在的表中引用外键

到目前为止,我找到的最佳解决方案是使用
DependencyWalker.discoverdependences()
获取 依赖关系树,
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);
用户、视图和存储过程的脚本如下:

        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);
            }
        }

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

我找到了一个解决方案,那就是使用每个对象的
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在此给出的代码示例:。这种方法的问题是,表没有特定的顺序编写脚本,但需要按照其依赖关系的顺序编写,以便定义约束和插入行。无法在尚不存在的表中引用外键

到目前为止,我找到的最佳解决方案是使用
DependencyWalker.discoverdependences()
获取 依赖关系树,
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);
用户、视图和存储过程的脚本如下:

        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);
            }
        }

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

您是否设法找到了一些解决方案?我想我基本上遵循了同样的步骤,然后开始进入这个泥潭,并决定必须有一个更简单的方法。我最终使用了备份和恢复。看@JonnyLeeds是的,这已经非常有效了。另外一个优点是生成的脚本在某种程度上是独立于版本的。生产站点使用SQL标准,但生成的脚本在SQLEXPRESS上工作,这对于根据真实数据的副本进行开发非常方便。@JonnyLeeds最后的调整是通过GZipStream保存脚本,使文件变小。远程连接速度很慢,但本地连接速度很快,因此我在生产服务器上以任务(每小时一次)的形式运行scripter并通过ftp发送结果。您是否成功使用了此功能?我想我基本上遵循了同样的步骤,然后开始进入这个泥潭,并决定必须有一个更简单的方法。我最终使用了备份和恢复。看@JonnyLeeds是的,这已经非常有效了。另外一个优点是生成的脚本在某种程度上是独立于版本的。生产站点使用SQL标准,但生成的脚本在SQLEXPRESS上工作,这对于根据真实数据的副本进行开发非常方便。@JonnyLeeds最后的调整是通过GZipStream保存脚本,使文件变小。在远程连接中速度很慢,但在本地连接时速度很快,因此我在生产服务器上以任务(每小时一次)的形式运行脚本并通过ftp传输结果。