Как получить доступ к коллекции переменных пакета в biml?

Я только начинаю работать с biml и bimlscript. Я вижу его силу, но до сих пор копаться в справочнике по языку и API было сложно. Кажется, я не могу найти в Интернете ссылку для доступа к коллекции переменных пакета.

Я пытаюсь настроить этот сценарий, чтобы я мог добавить больше переменных в свой раздел «Переменные», а затем автоматически добавить эти переменные в задачу сценария позже в процессе.

Вот минимальный код для моей проблемы:

<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
  <Packages>
    <Package Name="Load">
      <Variables>
        <Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
        <Variable Name="TenantID" DataType="Int32">1</Variable>
      </Variables>
      <!-- more stuff going on in the biml -->
       <# var package = RootNode.Packages.Where(loadPackage => loadPackage.Name.Contains("Load")); 
          foreach (var variable in package.Variables) { #>
            <ReadWriteVariables VariableName="<#=variable.Name#>" />   
       <# }#>
    </Package>
  </Packages>
</Biml>

Кажется, это самое близкое, что я получил. К сожалению, это приводит к:

Error   0   'System.Collections.Generic.IEnumerable<Varigence.Languages.Biml.Task.AstPackageNode>' does not contain a definition for 'Variables' and no extension method 'Variables' accepting a first argument of type 'System.Collections.Generic.IEnumerable<Varigence.Languages.Biml.Task.AstPackageNode>' could be found (are you missing a using directive or an assembly reference?).

Если я правильно читаю документацию, в узле Packages есть коллекция Variables. https://varigence.com/Documentation/Api/Type/AstPackageNode

Если я неправильно читаю документацию, может ли кто-нибудь указать мне ссылку на то, как я могу получить доступ к коллекции переменных пакета?


person Shannon Lowder    schedule 12.08.2016    source источник
comment
Из любопытства, чего вы пытаетесь достичь? ReadWriteVariables присоединяются к задачам/компонентам сценария, поэтому вы можете быстро немного из дистиллированного из образца. Что хорошо, коротко и по делу.   -  person billinkc    schedule 12.08.2016
comment
Все мои пакеты начинаются с оператора execute SQL, который ищет значения конфигурации для переменных в пакете на основе идентификатора ETLProcessStepID пакета. Эти значения передаются через объектную переменную задаче сценария, которая обновляет значения ReadWriteVariables. Различные типы пакетов имеют разные коллекции ReadWriteVariables. Я надеялся динамически добавлять переменные в задачу сценария через biml.   -  person Shannon Lowder    schedule 12.08.2016
comment
В этом случае вам не нужно будет использовать bimlscript для проверки пакета. Вместо этого установите соединение с вашим репозиторием, как обычный вызов .NET, и получите данные конфигурации. Затем поработайте с таблицей данных на C#, чтобы управлять созданием как переменных в пакете SSIS, так и переменных для задачи сценария.   -  person billinkc    schedule 12.08.2016
comment
Для проекта я переключусь на ваше предложение по созданию и назначению переменных в скрипте. Я все еще буду использовать ваши примеры выше, чтобы узнать больше о доступе к различным частям пакетов через biml. Это все для меня поучительно!   -  person Shannon Lowder    schedule 15.08.2016


Ответы (1)


Первая ошибка, с которой вы сталкиваетесь, заключается в том, что ваша переменная C# с именем package будет возвращать коллекцию из этого вызова Linq. Так как должен быть только один элемент, который соответствует ему, мы будем использовать First, чтобы просто дать нам одну из этих вещей.

var package = RootNode.Packages.Where(loadPackage => loadPackage.Name.Contains("Load")).First();

Теперь сложная часть, и мне действительно придется проверить это с помощью более крупных орудий, но я не думаю, что вы сможете получить доступ к коллекции переменных текущего пакета, потому что она еще не создана. Ну, по крайней мере, с помощью BIDS Helper/BimlExpress. Biml сначала нужно скомпилировать в объекты, потому что, предполагая одиночный выбор, у вас не будет ничего в коллекции RootNode.Packages. У вас определенно не было бы «Load», потому что вы компилируете его прямо сейчас.

В Mist, платном решении, которое вскоре будет переименовано в BimlStudio, для этого можно использовать Transformer. Сначала вы создадите пакет Load, а затем непосредственно перед излучением сработает преобразователь в виде пакета dtsx и сделает любую коррекцию, которую вы пытались сделать.

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

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <Packages>
        <Package Name="so_38908470" >
            <Variables>
                <Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
                <Variable Name="TenantID" DataType="Int32">1</Variable>
            </Variables>
    <#

    string message = "<!-- {0} -->";
    WriteLine(message, "test");
    foreach (var package in RootNode.Packages)
    {
        WriteLine(message, package.Name);
        foreach(var variable in package.Variables)
        {
            WriteLine(message, variable.Name);
        }
    }
    #>
        </Package>
    </Packages>
</Biml>

Чем больше я думаю об этом, тем больше я думаю, что Tiering может достичь этого с помощью BIDS Helper/BimlExpress. Поскольку похоже, что вы пытаетесь использовать переменные, определенные в пакете, в качестве входных данных для задачи или компонента сценария, пока вы используете вещи типа ScriptProjects, которые параллельны коллекции пакетов, это может работать.

Эврика

Добавьте в проект два файла Biml: Load.biml и Script.Biml. Используйте следующий код в каждом. Выберите оба и щелкните правой кнопкой мыши, чтобы создать пакет SSIS.

Загрузить.biml

Это будет ваш пакет. Это пакет, который вы запустили выше с помощью задачи сценария, которая собирается вывести имя и значение всех пользовательских переменных, объявленных в корне пакета. Но, как вы видите, в теге ScriptTask нет ничего, что указывало бы, какие переменные или что будет делать код.

<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
  <Packages>
    <Package Name="Load">
      <Variables>
        <Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
        <Variable Name="TenantID" DataType="Int32">1</Variable>
      </Variables>
            <Tasks>
                <Script ProjectCoreName="ST_EchoBack" Name="SCR Echo Back">
                    <ScriptTaskProjectReference ScriptTaskProjectName="ST_EchoBack" />
                </Script>            
            </Tasks>
    </Package>
  </Packages>
</Biml>

Скрипт.biml

Этот biml выглядит много, но это те же концепции, с которыми я работал выше, где я перечисляю коллекцию пакетов, а затем работаю с коллекцией переменных. Я использую слепки biml для управления эмиссией свойств Namespace, Name и DataType.

<#@ template language="C#" tier="1" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
<ScriptProjects>
        <ScriptTaskProject ProjectCoreName="ST_EchoBack" Name="ST_EchoBack" VstaMajorVersion="0">
            <ReadOnlyVariables>
                <!-- List all the variables you are interested in tracking -->
    <#
    string message = "<!-- {0} -->";
    WriteLine(message, "test");
//    ValidationReporter.Report(Severity.Error, "test");

    foreach (var package in RootNode.Packages.Where(x=> x.Name == "Load"))
    {
        WriteLine(message, package.Name);
//        ValidationReporter.Report(Severity.Error, package.Name);
        foreach(var variable in package.Variables)
        {
            WriteLine(message, variable.Name);
//            ValidationReporter.Report(Severity.Error, variable.Name);
            #>
            <Variable Namespace="<#=variable.Namespace#>" VariableName="<#=variable.Name#>" DataType="<#=variable.DataType#>" />
            <#
        }
    }
    #>
            </ReadOnlyVariables>
            <Files>
                <File Path="ScriptMain.cs" BuildAction="Compile">using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;

namespace ST_EchoBack
{
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
        public void Main()
        {
            bool fireAgain = false;
            string message = "{0}::{1} : {2}";
            foreach (var item in Dts.Variables)
            {
                Dts.Events.FireInformation(0, "SCR Echo Back", string.Format(message, item.Namespace, item.Name, item.Value), string.Empty, 0, ref fireAgain);
            }

            Dts.TaskResult = (int)ScriptResults.Success;
        }

        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
    }
}                </File>
                <File Path="Properties\AssemblyInfo.cs" BuildAction="Compile">
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyVersion("1.0.*")]
                </File>
            </Files>
            <AssemblyReferences>
                <AssemblyReference AssemblyPath="System" />
                <AssemblyReference AssemblyPath="System.Data" />
                <AssemblyReference AssemblyPath="System.Windows.Forms" />
                <AssemblyReference AssemblyPath="System.Xml" />
                <AssemblyReference AssemblyPath="Microsoft.SqlServer.ManagedDTS.dll" />
                <AssemblyReference AssemblyPath="Microsoft.SqlServer.ScriptTask.dll" />
            </AssemblyReferences>
        </ScriptTaskProject>
    </ScriptProjects>        
</Biml>

Я подумал, что могу упростить вызов GetBiml() переменной variable, но это будет выдавать точный biml, с которым он был определен

<Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
<Variable Name="TenantID" DataType="Int32">1</Variable>

и если бы там не было фактического значения, это был бы законный синтаксис для коллекции переменных ReadOnly/ReadWrite. Que последняя.

person billinkc    schedule 12.08.2016