无法在SSIS中生成用于分层的BIML脚本

时间:2019-02-19 19:20:36

标签: ssis biml

我遇到了这样的情况,我的主Biml生成了150个执行包任务。我需要生成序列容器,以便它们每个都包含主包中每个序列容器的(150/10)15个执行包任务。

欢迎您提出任何想法/工作示例/代码库,请帮我找到合适的解决方案!

<Tasks> 
    <# foreach (var package in RootNode.Packages) { #> 
         <ExecutePackage Name="Execute <#=package.Name#>" > 
              <ExternalProjectPackage Package="<#=package.PackageFileName#>" /> 
         </ExecutePackage>
    <# } #>
</Tasks> 

1 个答案:

答案 0 :(得分:5)

此答案将利用Biml的一些高级概念。首先是分层,因此我们将在第1层中生成150个程序包,然后在第2层(或比上一层更大的任何数字)中,我们将能够引用第0层至(第max层- 1)。

第0层是静态/扁平Biml(在此示例中没有)。由于我们将循环生成子程序包,因此它将自动位于第1层,但我选择在此处明确说明,以防您有先驱但动态的任务要解决

<#* .... #>是Biml编译器忽略的超强大注释构造

<#+ .... #>用于在Biml中添加显式方法和类

我们还将使用Extension method将我们的程序包大致分为几组,然后填充到序列容器中。

第1层

此代码生成名称为so_54773502_000到so_54773502_149(共150个)的空白SSIS包

<#@ 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();
}

#>

最终结果

看,很多软件包都在执行!

enter image description here

相关问题