【问题标题】:How to pass a List of custom objects in a SSIS Script Task?如何在 SSIS 脚本任务中传递自定义对象列表?
【发布时间】:2026-02-01 14:30:02
【问题描述】:

我有一个脚本任务,它创建一个自定义对象列表并将它们设置为一个 SSIS 对象变量。

自定义类:

public class Dog
{
    public string Name { get; set; }
}

填充列表并设置为 SSIS 对象变量“myDogs”的代码:

public void Main()
{
    List<Dog> dogs = new List<Dog>();

    Dog dog1 = new Dog();
    dog1.Name = "Fido";

    Dog dog2 = new Dog();
    dog1.Name = "Roofus";

    dogs.Add(dog1);
    dogs.Add(dog2);

    Dts.Variables["myDogs"].Value = dogs;
}

在第二个脚本任务中,我试图将“myDogs”对象变量读回列表:

在第二个脚本任务中复制的自定义类:

public class Dog
{
    public string Name { get; set; }
}

我的第二个脚本任务中的主要代码:

public void Main()
{
    var varDogs = Dts.Variables["myDogs"].Value;
    List<Dog> dogs = new List<Dog>();

    dogs = (List<Dog>)varDogs;
}

我的 varDogs 对象正确加载了我的 SSIS 对象变量“myDogs”中的数据。但是,当我尝试将 varDogs 转换为 Dog 类型的列表时,我收到一条错误消息,提示“无法转换 System.Collections.Generic.List 类型的对象”。

有谁知道我如何将这个 var 数据转换回列表?谢谢。

【问题讨论】:

  • 我怀疑您的问题将与 Dog 类的序列化有关,但今天没有时间查看它。也许它正在将 dog 实例的浅拷贝与深层拷贝添加到通用列表中。或者您需要为您的类提供一些显式序列化(因为.NET 认为它们是两个不同的类对象,即使它们具有相同的定义),我不知道。而且我今天没有有时间深入研究它。我不。大脑,真的,我。如果您只是尝试将 Dog 的实例添加到您的变量并在另一个脚本中反序列化,您将得到相同的错误。
  • 将其转换为数据表并以这种方式使用。

标签: c# ssis script-task


【解决方案1】:

在您尝试其他任何操作之前,请将您的自定义类编译为 .dll 并将其安装到您的 GAC(全局程序集缓存)。 SSIS 在与自定义对象交互时非常挑剔,它希望在那里找到对它们的引用。 GAC 安装的 MSDN 示例可以在 here 找到。安装 .dll 后,只需在脚本任务中引用它,SSIS 就会自动搜索 GAC 签名。

这是在 SSIS 中管理自定义对象的正确方法,因为您在两个脚本任务中都引用了 一个 类。尽管您当前的两个脚本任务之间的类相同,但您的错误表明它们来自不同的命名空间。

正如其他人所建议的那样,序列化会起作用,但它至少是一个骇人听闻的解决方案,因为您必须在两边都维护类(脚本任务 1 和脚本任务 2)。在开始使用复杂类型之前,最好先熟悉一下原生 SSIS 解决方案:)

【讨论】:

    【解决方案2】:

    使用 SSIS 时最简单的方法是使用 DataTable。在此示例中,我刚刚通过 SQL 任务填充了我的对象以简化它。

    C# 代码

    public class Dog
    {
        public string Name { get; set; }
    }
    
    public void Main()
    {
    
    
        DataTable dt = new DataTable();
        OleDbDataAdapter adapter = new OleDbDataAdapter();
        adapter.Fill(dt, Dts.Variables["User::myDogs"].Value);
    
    
        List<Dog> dogList = new List<Dog>();
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            Dog dogs = new Dog();
            dogs.Name = dt.Rows[i]["Name"].ToString();
            dogList.Add(dogs);
    
        }
            Dts.TaskResult = (int)ScriptResults.Success;
    }
    

    数据表结果

    列出结果

    【讨论】:

      【解决方案3】:

      看到您的推文并很好奇,但是当我第一次跳到这里时,我的脑海中就已经知道您正在做一些更接近实际 SQL Server 的事情,而我已经收集了几个链接供您查看。此外,这不太可能是一个“答案”,尽管它可能会在概念上有所帮助,特别是如果@billinkc 对序列化问题的想法是问题的一部分。免责声明,自从我从事 C++ 工作以来已经有很长一段时间了(是的,你知道你提到了 C#),老实说,我只是偶然发现了几次 SSIS。最近我花了很多时间在 JavaScript/TypeScript 世界中“让它工作”,因此有可能遵循的 hacky 建议。

      当我只看了一眼并立即去抓取几个链接时,我的想法是如果你将它编码为 JSON,尤其是使用新的 SQL Server 内置功能。然后抓住了一些关于在 SSIS 中使用 JSON 的文章,但最后是关于直接在 C# 中编码/解码 JSON 的文章。如果您实际上遇到了任何序列化/克隆/深拷贝/类型推断问题,我猜这实际上可能会有所帮助。

      如果您不熟悉 JavaScript,获取数据对象的“深度副本”的一种相当老套的方法是将其转换为 JSON,然后再返回。请记住,JSON 只是字符串数据,因此不应包含对象引用/复杂类型。问题只是您是否可以正确地将 JSON 解码的输出投射到“另一边”。

      希望你把你的狗都整理好……

      【讨论】:

        【解决方案4】:

        尝试将[Serializable()] 属性添加到您的对象。

        【讨论】: