从变量使用OLE DB Source命令的EzAPI等价物是什么?

bil*_*nkc 10 c# ssis ezapi

TL;博士

什么是使用OLE DB源的EzAPI代码,数据访问模式为"来自变量的SQL命令"并分配变量?

前言

每月一次,我们需要使用生产数据子集刷新公共测试站点.我们已经确定,根据我们的需求,SSIS解决方案最适合完成此任务.

我的目标是系统地构建大量(100+)"复制"包.EzAPISSIS对象模型的友好包装器,它似乎是一种保存鼠标点击的好方法.

我希望我的包装看起来像

  • 变量 - "tableName"; [架构].[表名]
  • 变量 - "sourceQuery"; SELECT*FROM [Schema].[TableName]
  • DataFlow - "Replicate Schema_TableName"
    • OLE DB源 - "Src Schema_TableName"; 数据访问模式:来自变量的SQL命令; 变量名:User::sourceQuery
    • OLE DB目标 - "Dest Schema_TableName"; 表或视图名称变量 - 快速加载; 变量名称 - User :: tableName

这是我的表到表复制包的代码.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.SSIS.EzAPI;
using Microsoft.SqlServer.Dts.Runtime;

namespace EzApiDemo
{
    public class TableToTable : EzSrcDestPackage<EzOleDbSource, EzSqlOleDbCM, EzOleDbDestination, EzSqlOleDbCM>
    {
        public TableToTable(Package p) : base(p) { }

        public static implicit operator TableToTable(Package p) { return new TableToTable(p); }


        public TableToTable(string sourceServer, string database, string table, string destinationServer) : base()
        {
            string saniName = TableToTable.SanitizeName(table);
            string sourceQuery = string.Format("SELECT D.* FROM {0} D", table);

            // Define package variables
            this.Variables.Add("sourceQuery", false, "User", sourceQuery);
            this.Variables.Add("tableName", false, "User", table);

            // Configure DataFlow properties
            this.DataFlow.Name = "Replicate " + saniName;
            this.DataFlow.Description = "Scripted replication";

            // Connection manager configuration
            this.SrcConn.SetConnectionString(sourceServer, database);
            this.SrcConn.Name = "PROD";
            this.SrcConn.Description = string.Empty;

            this.DestConn.SetConnectionString(destinationServer, database);
            this.DestConn.Name = "PREPROD";
            this.DestConn.Description = string.Empty;

            // Configure Dataflow's Source properties
            this.Source.Name = "Src " + saniName;
            this.Source.Description = string.Empty;
            this.Source.SqlCommand = sourceQuery;

            // Configure Dataflow's Destination properties
            this.Dest.Name = "Dest " + saniName;
            this.Dest.Description = string.Empty;
            this.Dest.Table = table;
            this.Dest.FastLoadKeepIdentity = true;
            this.Dest.FastLoadKeepNulls = true;
            this.Dest.DataSourceVariable = this.Variables["tableName"].QualifiedName;
            this.Dest.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD_VARIABLE;
            this.Dest.LinkAllInputsToOutputs();
        }

        /// <summary>
        /// Sanitize a name so that it is valid for SSIS objects. 
        /// Strips []/\:=
        /// Replaces . with _
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string SanitizeName(string name)
        {
            string saniName = name.Replace("[", String.Empty).Replace("]", string.Empty).Replace(".", "_").Replace("/", string.Empty).Replace("\\", string.Empty).Replace(":", string.Empty);
            return saniName;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

调用看起来像TableToTable s2 = new TableToTable(@"localhost\localsqla", "AdventureWorks", "[HumanResources].[Department]", @"localhost\localsqlb");构建一个包,除了在源中使用变量之外,它可以执行我想要的操作.

问题

上面的代码提供访问模式作为SQL查询,查询嵌入在OLE源中.希望它使用"来自变量的SQL命令",并且该变量是@[User::sourceQuery] 我所坚持的是在源中使用变量.

应该是分配像一个简单的问题

        this.Source.DataSourceVariable = this.Variables["sourceQuery"].QualifiedName;
        this.Source.AccessMode = AccessMode.AM_SQLCOMMAND_VARIABLE;
Run Code Online (Sandbox Code Playgroud)

这会导致选择正确的数据访问模式,但不会填充变量. ole db source

你可以看到,我执行了目的地了类似的步骤接受变量和作品"的权利."

        this.Dest.DataSourceVariable = this.Variables["tableName"].QualifiedName;
        this.Dest.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD_VARIABLE;
Run Code Online (Sandbox Code Playgroud)

目的地与变量

什么行不通

列出我尝试过的排列

        this.Source.AccessMode = AccessMode.AM_OPENROWSET;
Run Code Online (Sandbox Code Playgroud)

数据访问模式中的结果设置为表或视图和表的名称或视图为空.

        this.Source.AccessMode = AccessMode.AM_OPENROWSET_VARIABLE;
Run Code Online (Sandbox Code Playgroud)

数据访问模式中的结果设置为"表或视图名称变量",变量名称为sourceQuery.非常接近我想要的,除了访问模式不正确.如果这个包运行,它会爆炸,因为OpenRowSet会期望一个直接的表名.

        this.Source.AccessMode = AccessMode.AM_SQLCOMMAND;
Run Code Online (Sandbox Code Playgroud)

数据访问模式中的结果设置为"SQL命令",SQL命令文本为"User :: sourceQuery"这是变量名称的字面值,因此它是正确的,但由于访问模式错误,它不起作用.

        this.Source.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD;
        this.Source.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD_VARIABLE;
Run Code Online (Sandbox Code Playgroud)

其中没有这些是正确的访问模式,因为它们是目的地(我仍然尝试过但他们没有按预期工作).

在这一点上,我想我会尝试通过创建一个包含OLE DB源的包来反向工作,然后检查源对象的属性.

        Application app = new Application();
        Package p = app.LoadPackage(@"C:\sandbox\SSISHackAndSlash\SSISHackAndSlash\EzApiPackage.dtsx", null);
        TableToTable to = new TableToTable(p);
Run Code Online (Sandbox Code Playgroud)

来源属性

我的代码使用变量的限定名称设置了SqlCommand和DataSourceVarible.我已经下载了变更集65381并编译了(在修复了对SQL Server 2012 dll的一些引用之后)希望自2008年12月30日Stable构建以来可能已经有一个修复但无济于事.

我是否在代码中发现了错误,或者我错过了什么?

bil*_*nkc 12

EzAPI的当前稳定版本不支持将变量赋值为OleDB Source属性.我在CodePlex上开了一个类似的讨论,最后了解了所有这些的工作原理.

根问题是当访问模式设置为"来自变量的SQL命令"时,应设置相关属性"SqlCommandVariable".目前,代码仅涵盖目标变量.

我的决心是下载源代码并修改DataSourceVariableEzComponents.cs中属性的setter (更改集65381的第1027行)

        set 
        { 
            m_comp.SetComponentProperty("OpenRowsetVariable", value); 
            if (AccessMode == AccessMode.AM_SQLCOMMAND_VARIABLE)
            {
                m_comp.SetComponentProperty("SqlCommandVariable", value); 
            }
            ReinitializeMetaData(); 
        } 
Run Code Online (Sandbox Code Playgroud)

如果您希望正确解决此问题,可以提出问题

  • Serial Downvoter([@TheOptimusPrimus](http://stackoverflow.com/users/2517150/theoptimusprimus))我看到你把它投票为"没用".我正在哭泣的眼泪.你能不能提供一些无用的背景,以便我可以改善这个残暴的,排泄的答案? (3认同)