BIML SSIS ScriptTask 作为数据源 - OutputBuffer 出错
BIML SSIS ScriptTask as a data source - Error with OutputBuffer
尝试使用 ScriptTask 作为数据源通过 BIML 生成包时出现以下错误。我有一个大(大约 5GB)XML 文件要加载,我想使用 StreamReader 将数据导入数据库。
'Output0Buffer' does not contain a definition for 'PORTF_LIST' and no extension method 'PORTF_LIST' accepting a first argument of type 'Output0Buffer' could be found (are you missing a using directive or an assembly reference?).
每一列都会发生这种情况。这些列是动态的,来自 c# class 查看 dacpac 中的单独方法,因此在任何地方都应该具有相同的名称和大小写。
文件示例如下:
<ANALYTICS>
<INSTRUMENTS ASOF_DATE="3/31/2017" CREATE_DATE="4/2/2017" RECORDS="3763">
<INSTRUMENT>
<PORTF_LIST>XX1245897</PORTF_LIST>
<PRT_FULL_NAME>Convertible Bonds</PRT_FULL_NAME>
<ISIN>11803384</ISIN>
</INSTRUMENT>
</INSTRUMENTS>
</ANALYTICS>
输出缓冲区定义如下(有250个奇数列,但都遵循相同的模式:
<OutputBuffers>
<OutputBuffer Name="Output0" IsSynchronous="false">
<Columns>
<Column Name="PORTF_LIST" DataType="String" Length="255"/>
<Column Name="PRT_FULL_NAME" DataType="String" Length="255"/>
<Column Name="ISIN" DataType="String" Length="255"/>
</Columns>
</OutputBuffer>
</OutputBuffers>
我试图添加到缓冲区的脚本任务代码如下:
<#@ property name="Elements" type="String" #>
<#@ property name="Columns" type="String" #>
<#@ property name="BufferColumns" type="String" #>
<#@ property name="RootElement" type="String" #>
<ScriptComponentProject ProjectCoreName="SC_eb1debcd2374468ebccbbfad4fbe5976" Name="XmlSource">
<AssemblyReferences>
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSPipelineWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSRuntimeWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.PipelineHost" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.TxScript" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ManagedDTS.dll" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ScriptTask.dll" />
<AssemblyReference AssemblyPath="System.dll" />
<AssemblyReference AssemblyPath="System.AddIn.dll" />
<AssemblyReference AssemblyPath="System.Data.dll" />
<AssemblyReference AssemblyPath="System.Windows.Forms.dll" />
<AssemblyReference AssemblyPath="System.Xml.dll" />
<AssemblyReference AssemblyPath="System.Xml.Linq.dll" />
<AssemblyReference AssemblyPath="System.Core.dll" />
</AssemblyReferences>
<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="Output0" IsSynchronous="false">
<Columns>
<#=BufferColumns#>
</Columns>
</OutputBuffer>
</OutputBuffers>
<Files>
<File Path="Properties\AssemblyInfo.cs">
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("XmlSource")]
[assembly: AssemblyDescription("Script Component as source")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("XmlSource")]
[assembly: AssemblyCopyright("Copyright @ 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.*")]
</File>
<File Path="main.cs">
<![CDATA[
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Security;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Windows.Forms;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public string sourceFile = Dts.Variables["User::FileName"].Value.ToString();
public override void CreateNewOutputRows()
{
foreach (var myXmlData in (
from elements in StreamReader(sourceFile, "INSTRUMENT")
select new
{
PORTF_LIST = elements.Element("PORTF_LIST").Value,
PRT_FULL_NAME = elements.Element("PRT_FULL_NAME").Value,
ISIN = elements.Element("ISIN").Value
}
))
{
try
{
Output0Buffer.AddRow();
Output0Buffer.PORTF_LIST = myXmlData.PORTF_LIST;
Output0Buffer.PRT_FULL_NAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN;
}
catch (Exception e)
{
string errorMessage = string.Format("Data retrieval failed: {0}", e.Message);
bool cancel;
ComponentMetaData.FireError(0, ComponentMetaData.Name, errorMessage,string.Empty,0, out cancel);
}
}
}
public static IEnumerable<XElement> StreamReader(String filename, string elementName)
{
// Create an XML reader for this file.
using (XmlReader reader = XmlReader.Create(filename))
{
reader.MoveToContent(); // will not advance reader if already on a content node; if successful, ReadState is Interactive
reader.Read(); // this is needed, even with MoveToContent and ReadState.Interactive
while(!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if(reader.NodeType == XmlNodeType.Element && reader.Name.Equals(elementName))
{
// this advances the reader...so it's either XNode.ReadFrom() or reader.Read(), but not both
var matchedElement = XNode.ReadFrom(reader) as XElement;
if(matchedElement != null)
yield return matchedElement;
}
else
reader.Read();
}
reader.Close();
}
}
}
]]>
</File>
</Files>
<ReadOnlyVariables>
<Variable Namespace="User" DataType="String" VariableName="FileName" />
</ReadOnlyVariables>
<ReadWriteVariables>
</ReadWriteVariables>
</ScriptComponentProject>
我检查了控制台应用程序中的代码,它可以正常读取 XML 文件,但 BIML 不走运。大约有 250 列奇数,所以我尽量避免手动执行此操作,所以如果您对我做错了什么有任何想法,我将不胜感激!
似乎脚本任务不喜欢 OutputBuffer 中的下划线。
我手动创建了一个存根包,在分配值时,intellisense 使用的是 PORTFLIST 而不是 PORTF_LIST。
所以代码片段应该是:
Output0Buffer.AddRow();
Output0Buffer.PORTFLIST = myXmlData.PORTF_LIST;
Output0Buffer.PRTFULLNAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN
我还有一个错误,我最喜欢的"EmitSsis. Internal Compiler Error: Workflow EmitSsis contains fatal errors.",但至少这个错误已经解决了!
感谢 Bill 的帮助,很抱歉,我在发布的错误中用错误的列名带你去了花园小径,否则你可能已经知道这个问题了!
尝试使用 ScriptTask 作为数据源通过 BIML 生成包时出现以下错误。我有一个大(大约 5GB)XML 文件要加载,我想使用 StreamReader 将数据导入数据库。
'Output0Buffer' does not contain a definition for 'PORTF_LIST' and no extension method 'PORTF_LIST' accepting a first argument of type 'Output0Buffer' could be found (are you missing a using directive or an assembly reference?).
每一列都会发生这种情况。这些列是动态的,来自 c# class 查看 dacpac 中的单独方法,因此在任何地方都应该具有相同的名称和大小写。
文件示例如下:
<ANALYTICS>
<INSTRUMENTS ASOF_DATE="3/31/2017" CREATE_DATE="4/2/2017" RECORDS="3763">
<INSTRUMENT>
<PORTF_LIST>XX1245897</PORTF_LIST>
<PRT_FULL_NAME>Convertible Bonds</PRT_FULL_NAME>
<ISIN>11803384</ISIN>
</INSTRUMENT>
</INSTRUMENTS>
</ANALYTICS>
输出缓冲区定义如下(有250个奇数列,但都遵循相同的模式:
<OutputBuffers>
<OutputBuffer Name="Output0" IsSynchronous="false">
<Columns>
<Column Name="PORTF_LIST" DataType="String" Length="255"/>
<Column Name="PRT_FULL_NAME" DataType="String" Length="255"/>
<Column Name="ISIN" DataType="String" Length="255"/>
</Columns>
</OutputBuffer>
</OutputBuffers>
我试图添加到缓冲区的脚本任务代码如下:
<#@ property name="Elements" type="String" #>
<#@ property name="Columns" type="String" #>
<#@ property name="BufferColumns" type="String" #>
<#@ property name="RootElement" type="String" #>
<ScriptComponentProject ProjectCoreName="SC_eb1debcd2374468ebccbbfad4fbe5976" Name="XmlSource">
<AssemblyReferences>
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSPipelineWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSRuntimeWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.PipelineHost" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.TxScript" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ManagedDTS.dll" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ScriptTask.dll" />
<AssemblyReference AssemblyPath="System.dll" />
<AssemblyReference AssemblyPath="System.AddIn.dll" />
<AssemblyReference AssemblyPath="System.Data.dll" />
<AssemblyReference AssemblyPath="System.Windows.Forms.dll" />
<AssemblyReference AssemblyPath="System.Xml.dll" />
<AssemblyReference AssemblyPath="System.Xml.Linq.dll" />
<AssemblyReference AssemblyPath="System.Core.dll" />
</AssemblyReferences>
<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="Output0" IsSynchronous="false">
<Columns>
<#=BufferColumns#>
</Columns>
</OutputBuffer>
</OutputBuffers>
<Files>
<File Path="Properties\AssemblyInfo.cs">
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("XmlSource")]
[assembly: AssemblyDescription("Script Component as source")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("XmlSource")]
[assembly: AssemblyCopyright("Copyright @ 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.*")]
</File>
<File Path="main.cs">
<![CDATA[
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Security;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Windows.Forms;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public string sourceFile = Dts.Variables["User::FileName"].Value.ToString();
public override void CreateNewOutputRows()
{
foreach (var myXmlData in (
from elements in StreamReader(sourceFile, "INSTRUMENT")
select new
{
PORTF_LIST = elements.Element("PORTF_LIST").Value,
PRT_FULL_NAME = elements.Element("PRT_FULL_NAME").Value,
ISIN = elements.Element("ISIN").Value
}
))
{
try
{
Output0Buffer.AddRow();
Output0Buffer.PORTF_LIST = myXmlData.PORTF_LIST;
Output0Buffer.PRT_FULL_NAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN;
}
catch (Exception e)
{
string errorMessage = string.Format("Data retrieval failed: {0}", e.Message);
bool cancel;
ComponentMetaData.FireError(0, ComponentMetaData.Name, errorMessage,string.Empty,0, out cancel);
}
}
}
public static IEnumerable<XElement> StreamReader(String filename, string elementName)
{
// Create an XML reader for this file.
using (XmlReader reader = XmlReader.Create(filename))
{
reader.MoveToContent(); // will not advance reader if already on a content node; if successful, ReadState is Interactive
reader.Read(); // this is needed, even with MoveToContent and ReadState.Interactive
while(!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if(reader.NodeType == XmlNodeType.Element && reader.Name.Equals(elementName))
{
// this advances the reader...so it's either XNode.ReadFrom() or reader.Read(), but not both
var matchedElement = XNode.ReadFrom(reader) as XElement;
if(matchedElement != null)
yield return matchedElement;
}
else
reader.Read();
}
reader.Close();
}
}
}
]]>
</File>
</Files>
<ReadOnlyVariables>
<Variable Namespace="User" DataType="String" VariableName="FileName" />
</ReadOnlyVariables>
<ReadWriteVariables>
</ReadWriteVariables>
</ScriptComponentProject>
我检查了控制台应用程序中的代码,它可以正常读取 XML 文件,但 BIML 不走运。大约有 250 列奇数,所以我尽量避免手动执行此操作,所以如果您对我做错了什么有任何想法,我将不胜感激!
似乎脚本任务不喜欢 OutputBuffer 中的下划线。
我手动创建了一个存根包,在分配值时,intellisense 使用的是 PORTFLIST 而不是 PORTF_LIST。
所以代码片段应该是:
Output0Buffer.AddRow();
Output0Buffer.PORTFLIST = myXmlData.PORTF_LIST;
Output0Buffer.PRTFULLNAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN
我还有一个错误,我最喜欢的"EmitSsis. Internal Compiler Error: Workflow EmitSsis contains fatal errors.",但至少这个错误已经解决了!
感谢 Bill 的帮助,很抱歉,我在发布的错误中用错误的列名带你去了花园小径,否则你可能已经知道这个问题了!