使用 C# 转换器从 PostExecute 中的列表填充 OutputBuffer

Populate OutputBuffer from a List in PostExecute using C# transformer

尝试将平面文件分割成可用位的传奇还在继续!

您可能会从我的其他问题中看出,我正在尝试使用 SSIS 中的 C# 转换器将一些平面文件数据整理成各种位。当前的挑战是尝试将选择的一列行变成一行多列。

一位朋友非常友好地建议我使用 List,然后以某种方式在 PostExecute() 中循环遍历它。

主要问题是我不知道如何循环并创建一行以编程方式添加到输出缓冲区 - 平面文件中列出的字段数量可能不定,不一致。现在,我已经允许 100 个输出并将这些称为 pos1、pos2 等。

我真正想做的是计算列表中的所有内容,并循环多次,相应地递增数字 - 即 fieldlist[0] 转到 OutputBuffer.pos1,fieldlist[1] 转到 OutputBuffer。 pos2,如果在此之后没有任何内容,则不会将任何内容放入 pos3 到 pos100。

第二个问题是我什至无法通过在 PostExecute 中专门使用 OutputBuffer 来测试我的列表和写入输出 table 是否正常工作,更不用说循环了。

文件里面有各种各样的东西,但是字段列表很容易包含在 START-OF-FIELDS 和 END-OF-FIELDS 之间,所以我使用与以前相同的逻辑只处理中间。

bool passedSOF;
bool passedEOF;

List<string> fieldlist = new List<string>();

public override void PostExecute()
{
base.PostExecute();

OutputBuffer.AddRow();
OutputBuffer.field1=fieldlist[0];
OutputBuffer.field2=fieldlist[1];
}

public override void Input_ProcessInputRow(InputBuffer Row)
{
if (Row.RawData.Contains("END-OF-FIELDS"))
{
passedEOF = true;
OutputBuffer.SetEndOfRowset();
}

if (passedSOF && !passedEOF)
{
fieldlist.Add(Row.RawData);
}

if(Row.RawData.Contains("START-OF-FIELDS"))
{
passedSOF = true;
}
}

我没有用红色下划线,但是当我尝试 运行 时,我收到一条关于 PostExecute() 和 "object reference not set to an instance of an object" 的错误消息,我认为这意味着某些东西在应该包含 null 的地方't,但在我的测试文件中,START 和 END 标记之间有两个以上的字段。

所以首先,我在上面的示例中做错了什么,其次,我如何在正确的循环中执行此操作?目前只有 100 个可能的输出,但这可能会随着时间的推移而增加。

"Post execute" 之所以这样命名是有原因的。

您的数据流的执行已结束,此方法用于清理或执行后需要发生的任何事情 - 例如修改 SSIS 变量。缓冲区已经消失,此时无法与缓冲区的内容进行交互。

至于你的问题陈述的其余部分......它需要重点

所以我又一次误解了一个基本概念——PostExecute不能用我尝试的方式写出来。正如人们指出的那样,这里无法对缓冲区内容做任何事情。

我不能把这个答案归功于我,因为比我聪明的人又来拯救了,但我已经得到他们的许可 post 代码,以防它对任何人有用。我希望我已经解释清楚了,因为我只是自己理解它,并且在我进行的过程中学到了很多东西。

首先,请确保您的命名空间中包含以下内容:

using System.Reflection;
using System.Linq;
using System.Collections.Generic;

这些将用于获取输出缓冲区的属性,并允许我将列表中的第一项输出到 pos_1,第二项输出到 pos_2,等等。

像往常一样,我有两个布尔变量来确定我是否已经传递了指示我想要的数据行已经开始或结束的行,并且我有我的列表。

bool passedSOF;
bool passedEOF;

List<string> fieldlist = new List<string>();

这里是不同的地方 - 因为我有一些东西表明我已经处理完我的行,这是包含 END-OF-FIELDS 的行,当我到达那个点时,我应该写出我收集的列表到我的输出缓冲区。目的是获取所有包含字段名称的多行,并将其转换为具有多列的单行,字段名称按照它们出现的行顺序填充在这些列中。

if (Row.RawData.Contains("END-OF-FIELDS"))
{
passedEOF = true;

//IF WE HAVE GOT TO THIS POINT, WE HAVE ALL THE DATA IN OUR LIST NOW
OutputBuffer.AddRow();

var fields = typeof(OutputBuffer).GetProperties();

//SET UP AND INITIALISE A VARIABLE TO HOLD THE ROW NUMBER COUNT
int rowNumber = 0;

foreach (var fieldName in fieldList)
{
//ADD ONE TO THE CURRENT VALUE OF rowNumber
rowNumber++;

//MATCH THE ROW NUMBER TO THE OUTPUT FIELD NAME
PropertyInfo field = fields.FirstOrDefault(x = > x.Name == string.Format("pos{0}", rowNumber));

if (field != null)
{
field.SetValue(OutputBuffer, fieldName);
}
}
OutputBuffer.SetEndOfRowset();
}

if (passedSOF && !passedEOF)
{
this.fieldList.Add(Row.RawData);
}

if (Row.RawData.Contains("START-OF-FIELDS"))
{
passedSOF = true;
}

所以不要有这样的东西:

  • 开场白
  • 水果
  • 乳制品
  • 淀粉
  • 场结束

我有输出:

pos_1 | pos_2 | pos_3

水果 |乳制品 |淀粉

所以我可以构建一个位置键 table 来显示当前月度文件中哪个字段将以哪个顺序出现,现在我期待着让自己在拆分实际数据行时遇到更多麻烦进入另一个 table :)