首页 > 解决方案 > 使用 C# 转换器从 PostExecute 中的列表填充 OutputBuffer

问题描述

试图将平面文件切成可用位的传奇仍在继续!

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

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

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

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

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

该文件中有各种各样的内容,但字段列表很容易包含在 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() 和“对象引用未设置为对象的实例”的错误消息,我认为这意味着某些内容不应该包含 null ,但在我的测试文件中,我在 START 和 END 标记之间有两个以上的字段。

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

标签: c#ssis

解决方案


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

我不能把这个答案归功于这个答案,因为比我更聪明的人再次来救援,但我已经获得了他们的许可,可以发布代码,以防它对任何人有用。我希望我已经解释了这一点,因为我自己只是理解它,并且在我前进的过程中正在学习。

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

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

水果 | 乳制品 | 淀粉

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


推荐阅读