使用 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 服务器数据库中编写对象定义脚本的主要内容,如果未能解决你的问题,请参考以下文章