使用 SMO 在并行循环中从 .net 中的 SQL 服务器数据库中编写对象定义脚本

Posted

技术标签:

【中文标题】使用 SMO 在并行循环中从 .net 中的 SQL 服务器数据库中编写对象定义脚本【英文标题】:Using SMO to script out Object definitions from SQL server database in .net in Parallel loop 【发布时间】:2012-03-24 16:22:55 【问题描述】:

我正在使用 SMO 使用 .Net 代码从 Sql 服务器数据库中编写我的对象脚本。但到目前为止,我正在经历一个顺序循环。

foreach(var table in TableCollection)

 var stringCollection=table.Script();

它工作正常。但是,当我将相同的循环转换为 Parallel.ForEach 循环时:

Parallel.ForEach(TableCollection,table=>

 var stringCollection=table.Script();
);

它无法编写脚本。有没有人使用过相同的方法或任何其他方法从 Sql server 中并行编写对象?

更新:

到目前为止,我还无法计算出 Parallel LOOP,但我使用了下面提到的代码:

 server.SetDefaultInitFields(true);                

它在一定程度上提高了性能。

【问题讨论】:

它到底是怎么失败的?它会引发一些异常吗? 是的,它会抛出异常,表明已经有一个与此命令关联的 OPEN 数据读取器。可能当两个线程并行尝试编写 SERVER 对象的脚本时(因为正在使用相同的实例)会导致问题. 【参考方案1】:

似乎 SMO 不是以线程安全的方式构建的。当您在Table 上调用Script() 时,它使用来自其Server 的一些共享状态,因此您不能在来自同一个Server 的两个表上执行它。但是您可以通过为每个 Table 创建新的 Server 对象来解决这个问题:

private static TableCollection GetTables()

    Server server = new Server(…);
    Database database = server.Databases[…];
    var tables = database.Tables;
    return tables;


…

Parallel.For(0, GetTables().Count,
    i =>
    
        var stringCollection = GetTables()[i].Script();
        …
    );

这将使您的查询并行,但我不知道它是否会使它们实际上更快。

编辑:如果您想为每个线程创建一个Server,您可以使用允许线程本地初始化的Parallel.For() 的重载。比如:

Parallel.For(0, GetTables().Count,
    () => GetTables(),
    (i, _, tables) =>
    
        var stringCollection = tables[i].Script();
        …
        return tables;
    ,
    tables =>  );

这样,每个线程都会有自己的Server 对象,但只有一个。

【讨论】:

实际上这种方式我知道它会起作用..但问题是我有表格、SP 和所有其他可能的对象,所以这种方法似乎非常昂贵,尤其是在没有的时候。的对象以成千上万的方式运行。 在这种情况下,您只需确保每个线程都有一个 Server 但我不太确定如何访问并行循环中的线程,以便确保每个线程只有一个服务器对象。或者您指的是我们自己创建线程.. @PanditA,请参阅我对如何使用 Parallel.For() 的重载来执行此操作的答案的编辑。 @Svick..Thanx 更新..我也想出了类似的东西,也使用了你提到的上面的代码。但不是提高性能..它已经降级,因为要为每个线程使用不同的服务器,我们需要有那么多的连接。我仍在试图弄清楚..但只是一个问题,是否有任何已知的方法可以使用 .net 代码从 Sql 服务器编写对象定义的脚本。

以上是关于使用 SMO 在并行循环中从 .net 中的 SQL 服务器数据库中编写对象定义脚本的主要内容,如果未能解决你的问题,请参考以下文章

使用XE7并行库中的TTask(转)

机器学习详解SMO算法剖析(转载)

.NET中并行开发优化

R中的并行while循环

smo 的 IsSystemObject 属性

如何在 django 模板中从 for 循环中转义一行