如何根据生成的代码编译 BIMLScript

How to compile BIMLScript depending on generated code

我正在使用 BIML 创建带有 ScriptComponentProject 的 ScriptComponenteSource。 该项目包含以下内容(取自 Varigence 样本)

<ScriptProjects>
    <ScriptComponentProject Name="SC_AD-Accounts" TargetFrameworkVersion="NetFX461">
        <AssemblyReferences>
            <AssemblyReference AssemblyPath="System" />
            <AssemblyReference AssemblyPath="System.Data" />
            <AssemblyReference AssemblyPath="System.Windows.Forms" />
            <AssemblyReference AssemblyPath="System.Xml" />
            <AssemblyReference AssemblyPath="Microsoft.SqlServer.TxScript" />
            <AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSRuntimeWrap" />
            <AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSPipelineWrap" />
            <AssemblyReference AssemblyPath="Microsoft.SqlServer.PipelineHost" />
            <AssemblyReference AssemblyPath="System.DirectoryServices" />
        </AssemblyReferences>

        <OutputBuffers>
            <OutputBuffer Name="Output0">
                <Columns>
                    <Column Name="UUId" DataType="String" Length="255" />
                    <Column Name="Surname" DataType="String" Length="255" />
                    <Column Name="GivenName" DataType="String" Length="255" />
                    <Column Name="EmailAddress" DataType="String" Length="255" />
                    <Column Name="UPN" DataType="String" Length="255" />
                </Columns>
            </OutputBuffer>
        </OutputBuffers>

        <Files>
            <File Path="main.cs"><![CDATA[
using System;
using System.Data;
using System.DirectoryServices;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public partial class ScriptMain : UserComponent
{
    public override void CreateNewOutputRows()
    {
        /*
          Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
          For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
        */

        var searchBaseNames = new [] {
            "OU=UserP,OU=User,DC=MyDC",
            "OU=UserPS,OU=User,DC=MyDC",
            "OU=UserPSC,OU=User,DC=MyDC"
        };

        var propertiesToLoad = new [] {
            "sn",
            "givenName",
            "mail",
            "userPrincipalName",
            "objectGuid",
            "serialNumber"
        };

        foreach (var searchBaseName in searchBaseNames) {
            var searchBaseEntry = new DirectoryEntry("LDAP://" + searchBaseName);

            var directorySearcher = new DirectorySearcher(searchBaseEntry, "(objectClass=user)", propertiesToLoad, SearchScope.Subtree) {
                PageSize = 2500
            };

            foreach (SearchResult searchResult in directorySearcher.FindAll()) {
                var surname = searchResult.Properties["sn"][0] as string;
                var givenName = searchResult.Properties["givenName"][0] as string;
                var email = searchResult.Properties["mail"][0] as string;
                var upn = searchResult.Properties["userPrincipalName"][0] as string;

                string uuid = null;

                if(searchResult.Properties.Contains("serialNumber"))
                {
                    uuid = searchResult.Properties["serialNumber"][0] as string;
                    if(!string.IsNullOrEmpty(uuid))
                        uuid = uuid;
                }

                if(string.IsNullOrEmpty(uuid))
                {
                    var objectGuidBytes = searchResult.Properties["objectGuid"][0] as byte[];
                    var objectGuid = new Guid(objectGuidBytes);

                    uuid = objectGuid.ToString();
                }

                if(string.IsNullOrEmpty(surname) || string.IsNullOrEmpty(givenName) || 
                   string.IsNullOrEmpty(upn) || string.IsNullOrEmpty(email))
                {
                    continue;
                }

                Output0Buffer.AddRow();
                Output0Buffer.Surname = surname;
                Output0Buffer.GivenName = givenName;
                Output0Buffer.UPN = upn;
                Output0Buffer.EmailAddress = email;
            }
        }
    }
}
            ]]></File>
        </Files>
    </ScriptComponentProject>
</ScriptProjects>

这不会编译,因为 BIML 扩展不知道 Output0Buffer 和重写方法(它们将自动创建)。

有办法解决这个鸡蛋问题吗?

我写了博客, https://billfellows.blogspot.com/2015/10/biml-script-component-source.html

您需要将输出缓冲区的 IsSynchronous 属性 指定为 false。否则,它会将组件视为同步转换。

<OutputBuffer Name="Output0" IsSynchronous="false">

欢迎评论我的代码

        <OutputBuffers>
            <!--    
            Define what your buffer is called and what it looks like
            Must set IsSynchronous as false. Otherwise it is a transformation
            (one row enters, one row leaves) and not a source.
            -->
            <OutputBuffer Name="DemoOutput" IsSynchronous="false">
                <Columns>
                    <Column Name="SourceColumn" DataType="String" Length="50" /> 
                </Columns>                    
            </OutputBuffer>                                 
        </OutputBuffers>