Каков эквивалент EzAPI для использования команды OLE DB Source из переменной? - PullRequest
10 голосов
/ 19 января 2012

tl; dr

Что такое код EzAPI для использования источника OLE DB с режимом доступа к данным «Команда SQL из переменной» и назначения переменной?

Преамбула

Раз в месяц нам необходимо обновлять наш общедоступный тестовый сайт подмножествами производственных данных.Мы определили, что для наших нужд лучше всего подходит решение SSIS для выполнения этой задачи.

Моя цель - систематически создавать большое количество (более 100) пакетов «репликации». EzAPI - это дружественная оболочка для объектной модели SSIS , и, похоже, это отличный способ сэкономить щелчки мыши.

Я бы хотел, чтобы мои пакеты выглядели как

  • Переменная - "tableName";[Схема]. [TableName]
  • Переменная - "sourceQuery";SELECT * FROM [Schema]. [TableName]
  • DataFlow - «Репликация 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;
        }
    }
}

Вызов выглядит как 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;

Это приводит к правильному выбранному режиму доступа к данным, но переменная не заполняется.ole db source

Вы можете заметить, что я выполняю аналогичный шаг в пункте назначения, который принимает переменную и работает "правильно".

        this.Dest.DataSourceVariable = this.Variables["tableName"].QualifiedName;
        this.Dest.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD_VARIABLE;

destination with variable

Что не работает

Перечисление перестановок, которые я пытался

        this.Source.AccessMode = AccessMode.AM_OPENROWSET;

Результаты в режиме доступа к данным установлены на Table или View и имя таблицы илипредставление пустое.

        this.Source.AccessMode = AccessMode.AM_OPENROWSET_VARIABLE;

В результате в режиме доступа к данным установлено значение "Таблица или переменная имени представления", а имя переменной - sourceQuery.Очень близко к тому, что я хочу, кроме режима доступа не правильно.Если бы этот пакет запустился, он взорвался бы, поскольку OpenRowSet ожидал бы прямого имени таблицы.

        this.Source.AccessMode = AccessMode.AM_SQLCOMMAND;

В результате в режиме доступа к данным установлено значение «Команда SQL», а текст команды SQL - «Пользователь:: sourceQuery "Это буквальное значение имени переменной, так что это правильно, но поскольку режим доступа неправильный, он не работает.

        this.Source.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD;
        this.Source.AccessMode = AccessMode.AM_OPENROWSET_FASTLOAD_VARIABLE;

Ни один из них не является правильным режимом доступа, как дляместа назначения (я все еще пробовал их, но они не работали должным образом).

На этом этапе я подумал, что я попытаюсь работать в обратном направлении, создав пакет, у которого источник OLE DB определен так, как я хочу.и затем проверьте свойства исходного объекта.

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

Source properties

Мой код установил и SqlCommand, и DataSourceVarible с полным именем переменной.Я вытащил ревизию 65381 и скомпилировал ее (после исправления некоторых ссылок на библиотеки SQL Server 2012) в надежде, что исправление могло быть исправлено после стабильной сборки 30 декабря 2008 г., но безрезультатно.

нашли ошибку в их коде или я просто что-то упустил?

Ответы [ 2 ]

12 голосов
/ 23 января 2012

Текущая стабильная сборка EzAPI не поддерживает присвоение переменной в качестве свойства источника OleDB. Я открыл похожее обсуждение на CodePlex и в итоге узнал больше о том, как все это работает.

Основная проблема заключается в связанном свойстве «SqlCommandVariable» следует устанавливать, если для режима доступа установлено значение «Команда SQL из переменной». В настоящее время код охватывает только переменные назначения.

Я решил загрузить исходный код и изменить установщик для свойства DataSourceVariable в EzComponents.cs (строка 1027 для changeset 65381)

        set 
        { 
            m_comp.SetComponentProperty("OpenRowsetVariable", value); 
            if (AccessMode == AccessMode.AM_SQLCOMMAND_VARIABLE)
            {
                m_comp.SetComponentProperty("SqlCommandVariable", value); 
            }
            ReinitializeMetaData(); 
        } 

Если вы хотите решить эту проблему правильно, вы можете проголосовать за Проблема

2 голосов
/ 19 января 2012

Попробуйте поменяться местами

this.Source.DataSourceVariable = this.Variables["sourceQuery"].QualifiedName;

this.Source.AccessMode = AccessMode.AM_SQLCOMMAND_VARIABLE; 

до

this.Source.AccessMode = AccessMode.AM_SQLCOMMAND_VARIABLE; 

this.Source.DataSourceVariable = this.Variables["sourceQuery"].QualifiedName;

Я обнаружил, что порядок важнее обычного API.

...