ssis - Unable to generate BIML script for Tiering in SSIS
问题描述
I have a situation where my master biml generates 150 Execute package task.I need to generate sequence containers so that each of them holds (150/10)15 Execute package task per sequence container in the master package.
Could you please help me to find an appropriate solution any ideas/Working exmaples/code base are welcome!!
<Tasks>
<# foreach (var package in RootNode.Packages) { #>
<ExecutePackage Name="Execute <#=package.Name#>" >
<ExternalProjectPackage Package="<#=package.PackageFileName#>" />
</ExecutePackage>
<# } #>
</Tasks>
解决方案
这个答案将利用 Biml 的一些高级概念。第一个将是分层,因此我们将在第 1 层生成 150 个包。然后在第 2 层(或任何大于前一层的数字),我们将能够参考第 0 层到(最大层数 - 1)。
第 0 层是静态/平面 Biml(在本例中我们没有)。由于我们将循环生成子包,它将自动位于第 1 层,但我选择在此处明确说明,以防您有前驱但动态的任务要解决
<#* .... #>
是一个超级强大的注释结构,被 Biml 编译器忽略
<#+ .... #>
是用于将显式方法和类添加到 Biml 中的构造
我们还将使用扩展方法将我们的包大致拆分为组,然后填充到序列容器中。
第一层
此代码生成空白 SSIS 包,名称范围从 so_54773502_000 到 so_54773502_149(总共 150 个)
<#@ template tier="1" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<#foreach (int index in Enumerable.Range(0, 150)){#>
<Package Name="so_54773502_<#= string.Format("{0:000}", index) #>" />
<#}#>
</Packages>
</Biml>
2级
在这里,我们指定我们想要多少个并行容器。该Split
方法的结果是一个列表列表。对于外部容器列表中的每个元素,我们需要添加一个序列容器。对于弹出列表中的每个元素,我们需要枚举它并执行一个包任务。
<#@ template tier="2" #>
<#
int taskCountPerContainer = 10;
int currentContainerNumber = 0;
#>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<Package Name="master">
<Tasks>
<#*
This is such a fun bit of LINQ. I used the Split extension so handily defined on the linked question
I pass in a List of package names and how many buckets I want and it returns a list of lists
From there, we enumerate through the list bucket and for each element we find, we create a sequence
container. Then, for each element in the bucket, we add an Execute Package Task.
I was unable to Split an instance of AstPackageNodes as it resulted in the error below but the only reason
your sample needed the full object was to provide both Name and PackageFileName properties. We can derive
the second given the first
// foreach(var outerlist in Split(this.RootNode.Packages.ToList<AstPackageNode>(),taskCountPerContainer)){
// results in this error.
// Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
// TODO: Check with Varigence or run in C# project
*#>
<#foreach(var listOfPackages in Split(this.RootNode.Packages.Select(x => x.Name).ToList<string>(), taskCountPerContainer)){#>
<Container Name="SEQC_<#=currentContainerNumber++#>" ConstraintMode="Linear">
<Tasks>
<#foreach(var packageName in listOfPackages){#>
<ExecutePackage Name="EPT <#=packageName#>"><ExternalProjectPackage Package="<#=packageName#>.dtsx"/></ExecutePackage>
<#}#>
</Tasks>
</Container>
<#}#>
</Tasks>
</Package>
</Packages>
</Biml>
<#+
// https://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq
public static IList<List<T>> Split<T>(IList<T> source, int buckets)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / buckets)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
#>
最终结果
看,很多包都被执行了!
推荐阅读
- c++ - 使用抽象多态类型初始化 C++ 2D shared_ptr 数组
- javascript - 为使用 preventDefault() 设置父级的嵌套菜单启用最后一个子链接单击;
- ios - 从服务器获取 CKC 后 iOS FairPlay 视频不播放
- c++ - 在 C++ 模板中将变量作为参数传递
- angular - 延迟加载模块中 Angular Material 日期选择器的语言切换
- android - 尝试将 SearchView 添加到我的 appcompat 活动时出现 Nullpointerexception
- typescript - TypeScript 递归函数返回未定义
- laravel - vue-for循环内每个元素的不同数据
- reactjs - 如何在 Redux 和 React.js 中对异步多个请求使用 Loader
- javascript - 没有for循环的数组过滤器上的Javascript多个条件