jjzjj

c# - 以编程方式编写脚本 SSIS 包 - 动态 XML 到 OLE DB

coder 2024-07-01 原文

我一直在努力拼凑其他用户是如何完成他们的项目的,但我的理解仍然有限。

我想获取任何给定的 XML 源,创建数据流任务,并将其数据传递到与 XML 文件的表名匹配的 OLE DB 目标。使用可视化工具运行它意味着我无法执行动态数据流任务,因为元数据不会刷新。

我已经创建了一个创建包的脚本,但是当我在 Visual Studio 中打开包时,它有一个红色 x 表示输入列不能为零。当我向下钻取并查看 OLE DB 目标的映射时,然后单击确定 - 它会为我更正它。我不知道如何以编程方式执行此操作。

我见过其他人通过使用 foreach 循环并遍历输入列来解决它,但我似乎无法弄明白。

我还有一个单独的脚本,我试图用它来模仿几个人的脚本,但它有不同的问题。不确定如何将其作为附件发布

预先感谢您的帮助:)

编辑

我一直在尝试 BIML 获得积极的反馈,我会......但我想知道在短期内是否有人可以帮助我弄清楚为什么这不会为我的输入填写 ExternalMetaDataColumnId。我在下面发布了更新后的代码,其中的 foreach 循环没有按照我的预期进行。

谢谢 #地区 使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用系统文本; 使用 System.Threading.Tasks; 使用 Microsoft.SqlServer.Dts.Runtime; 使用 Microsoft.SqlServer.Dts.Pipeline.Wrapper; 使用 System.Xml; #endregion

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Initial Setup
            Application a = new Application();
            Package p = new Package();
            TaskHost t = p.Executables.Add("DTS.Pipeline") as TaskHost;
            t.Name = "DataFlow Task";
            t.Description = "Flat File to Database";
            MainPipe mp = t.InnerObject as MainPipe;
            #endregion

            #region Flat File Source in Dataflow Task
            IDTSComponentMetaData100 md = mp.ComponentMetaDataCollection.New(); 
            md.ComponentClassID = "Microsoft.XmlSourceAdapter"; 
            md.Name = "XML Source"; 
            CManagedComponentWrapper wrp = md.Instantiate(); 
            wrp.ProvideComponentProperties(); 

            #endregion

            #region Add connection manager to OLE DB
            ConnectionManager conn = p.Connections.Add("OLEDB");
            conn.Name = "westcoastuserDBO";
            conn.ConnectionString = "Data Source=SERVER;Initial Catalog=DBO;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;";
            #endregion


            #region XML Source Properties
            wrp.SetComponentProperty("XMLData", @"C:\Users\file.xml");
            wrp.SetComponentProperty("XMLSchemaDefinition", @"C:\Users\file.xsd");
            wrp.SetComponentProperty("AccessMode", 0);
            wrp.SetComponentProperty("UseInlineSchema", false);
            //below does not work
            //wrp.SetComponentProperty("XMLIntegerMapping", 0).TypeConverter = "Microsoft.SqlServer.Dts.Pipeline.XmlSourceAdapter + XMLIntegerMappingConverter";

            wrp.ReinitializeMetaData();
            wrp.ReleaseConnections();
            IDTSComponentMetaData100 md2 = mp.ComponentMetaDataCollection.New();
            md2.ComponentClassID = "Microsoft.OLEDBDestination";
            CManagedComponentWrapper wrp2 = md2.Instantiate();
            wrp2.ProvideComponentProperties();
            md2.Name = "OLE DB Connection";
            md2.UsesDispositions = true;
            md2.Version = 4;
            wrp2.SetComponentProperty("OpenRowset", "dbo.authorizations");
            #endregion

            IDTSPath100 path = mp.PathCollection.New();
            path.AttachPathAndPropagateNotifications(md.OutputCollection[0], md2.InputCollection[0]);

            IDTSInput100 input = md2.InputCollection[0];
            IDTSVirtualInput100 vInput = input.GetVirtualInput();

            //below taken from https://stackoverflow.com/questions/12587709/c-sharp-ssis-data-flow-component-creating-custom-input-columns
            IDTSExternalMetadataColumnCollection100 externalColumnCollection = input.ExternalMetadataColumnCollection;


            // Iterate through the virtual input column collection.
            foreach (IDTSVirtualInputColumn100 vColumn in vInput.VirtualInputColumnCollection)
            {
                // Call the SetUsageType method of the destination
                // to add each available virtual input column as an input column.
                wrp2.SetUsageType(
                   input.ID, vInput, vColumn.LineageID, DTSUsageType.UT_READONLY);
            }

            // Get the destination's default output collection
            IDTSOutputCollection100 outColl = md2.OutputCollection;

            // Iterate through the outputs in default output collection
            foreach (IDTSOutput100 output in outColl)
            {
                // Iterate through the default output columns in the output 
                int count = output.OutputColumnCollection.Count;
                foreach (IDTSOutputColumn100 outputColumn in output.OutputColumnCollection)
                {
                    // Get the output's external metadata column collection
                    IDTSExternalMetadataColumnCollection100 extMetadataColumnColl = output.ExternalMetadataColumnCollection;

                    // Iterate through the external metadata column collection's external metadata columns
                    foreach (IDTSExternalMetadataColumn100 extMetadataColumn in extMetadataColumnColl)
                    {
                        // Call the MapOutPutColumn method of the destination to map
                        // each available output column to an external metadata column 
                        wrp2.MapOutputColumn(
                            output.ID, outputColumn.ID, extMetadataColumn.ID, true);
                    }
                }
            }

            md2.RuntimeConnectionCollection[0].ConnectionManager = DtsConvert.GetExtendedInterface(conn);
            md2.RuntimeConnectionCollection[0].ConnectionManagerID = conn.ID;
            conn.AcquireConnection(null);




            #region Save Package to FileSystem
            string packageXml = @"C:\Users\test.dtsx";
            XmlDocument myPkgDocument = new XmlDocument();
            p.SaveToXML(ref myPkgDocument, null, null);
            a.SaveToXml(packageXml, p, null);
            #endregion
        }
    }
}

最佳答案

我认为问题是您没有将输入列映射到 OLEDB 目标,打开包后,如果您单击 OLEDB 目标并转到“映射”部分,它会根据列名自动映射列.其他人使用的 Foreach 循环是遍历列并将它们映射到相关的目标列。

关于动态创建SSIS包的文章很多,可以引用:

关于c# - 以编程方式编写脚本 SSIS 包 - 动态 XML 到 OLE DB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48798998/

有关c# - 以编程方式编写脚本 SSIS 包 - 动态 XML 到 OLE DB的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  5. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  6. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  7. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  8. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐