如何根据生成的代码编译 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>
我正在使用 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>