Как получить GraphLayout XML из программно сгенерированного пакета служб SSIS - PullRequest
2 голосов
/ 28 февраля 2020

Если вы открываете пакет служб SSIS DTSX в Visual Studio, конструктор создает некоторые дополнительные DesignTimeProperties внутри блока CDATA в конце пакета.

Это выглядит как

<DTS:DesignTimeProperties >< ![CDATA[<?xml version="1.0"?>
<!--This CDATA section contains the layout information of the package.The section includes information such as (x, y) coordinates, width, and height.-->
<!--If you manually edit this section and make a mistake, you can delete it. -->
<!--The package will still be able to load normally but the previous layout information will be lost and the designer will automatically re-arrange the elements on the design surface.-->
<Objects Version="8">
  <!--Each node below will contain properties that do not affect runtime behavior.-->
   <Package design-time-name="Package">
   <LayoutInfo >
     <GraphLayout Capacity="16" xmlns="clr-namespace:Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization;assembly=Microsoft.SqlServer.IntegrationServices.Graph" 
          xmlns:mssgle="clr-namespace:Microsoft.SqlServer.Graph.LayoutEngine;assembly=Microsoft.SqlServer.Graph" 
          xmlns:assembly="http://schemas.microsoft.com/winfx/2006/xaml" 
          xmlns:mssgm="clr-namespace:Microsoft.SqlServer.Graph.Model;assembly=Microsoft.SqlServer.Graph">
       <NodeLayout
         Size="146.5,41.5"
         Id="Package\Datenflusstask"
         TopLeft="71.9999971389772,45.7600003636678" />
       <NodeLayout
         Size="155,41.5"
         Id="Package\Datenflusstask 1"
         TopLeft="126.666661633386,127.573334347195" />
   ....

Проблема является то, что эта информация добавляется только в том случае, если пакет открывается в Visual Studio, а добавляется в проект служб Integration Services.

Если я создаю пакет с ManagedDTS программным путем, эта информация отсутствует.

Я нашел SerializerHelper класс внутри Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization пространства имен в сборке Microsoft.SqlServer.IntegrationServices.Graph.dll, где вы можете вызвать

var graphLayoutXml = SerializerHelper.Save(graphModelElement);

Но, к сожалению, координаты отсутствуют (NaN или 0,0 ..)

Сейчас я загрузил пакет в строку

string contents = String.Empty;
Microsoft.SqlServer.Dts.Runtime.Package package = 
    new Microsoft.SqlServer.Dts.Runtime.Package();
using (StreamReader r = new StreamReader("DemoPackageWithoutDesignTimeProperties.dtsx"))
{
    contents = r.ReadToEnd();
}
package.LoadFromXML(contents, null);

Затем получил ControlFlowElements через

ControlFlowGraphModelElement controlFlowGraphModelElement = 
    new ControlFlowGraphModelElement();
controlFlowGraphModelElement.Initialize(package as IDTSSequence);

Затем попытался получить GraphLayout Xml через

GraphModelElement graphModelElement = new GraphModelElement();
graphModelElement.Container = controlFlowGraphModelElement.Container;
var graphLayoutXml = SerializerHelper.Save(graphModelElement);    

Очевидно, я пропускаю некоторые макеты. Может кто-нибудь помочь с правильным способом ...

Я знаю несколько других классов в Microsoft.SqlServer.IntegrationServices.Graph.dll, таких как LayoutGraph, GraphLayout и GraphControl в Microsoft.SqlServer.Graph.dll, но, к сожалению, документация это не так полезно ..

1 Ответ

2 голосов
/ 03 марта 2020

Почему это не работает?

Прежде всего, я хотел бы начать с @Fredipux замечательных комментариев:

Эта структура GraphLayout описывает задачи и размер SSIS, расположение и размер компонентов. в Visual Studio SSIS Designer; макет определяется во время редактирования пакета. Когда пакет генерируется программно, макет конструктора не определяется, поскольку пакет создается вне VS Designer

Это верно !! Суть в том, что Microsoft.SqlServer.PipelineHost, Microsoft.SqlServer.DTSPipelineWrap, Microsoft.SqlServer.DTSRuntimeWrap и Microsoft.SqlServer.ManagedDTS являются оболочками. NET, которые позволяют создавать и выполнять пакеты программным образом, когда дизайн не имеет смысла. Если вы обращаетесь к официальной документации SSIS и просматриваете все разделы и подразделы, вы заметите, что упоминаются только эти три сборки, тогда как другие сборки, такие как Microsoft.SqlServer.IntegrationServices.Graph.dll, не упоминаются, так как они связаны между собой. проектировщику Visual Studio.

Вы можете просто заметить, что четыре упомянутые сборки принадлежат пространству имен Microsoft.SqlServer.Dts, а другая - Microsoft.SqlServer.IntegrationServices.

Как упорядочить задачи в Visual Studio?

Обратите внимание, что в Visual Studio в полосе меню вы можете go до

Format >> Auto Layout >> Diagram

enter image description here

Тогда все задачи в потоке управления будут упорядочены .

В официальной документации я искал все свойства и методы, перечисленные для ManagedDTS и других. сборки, но я не нашел упомянутое, что вы можете использовать AutoLayout() метод. Кроме того, я не нашел эту опцию доступной даже при использовании ezApi и BIML.

Кроме того, я попытался использовать обозреватель объектов Visual Studio для поиска этого метода без удачи.

Что-то попробуйте

Я думаю, что самый простой способ добавить макет - это создать предложение макета XML вручную (взять структуру XML, сформировать существующий пакет и изменить свойства Id, size и TopLeft) и добавить его. к пакету XML.

После запуска многих примеров это выглядит возможным, но очень сложным, когда имеется много связанных задач. В следующих подразделах я проиллюстрировал некоторую полезную информацию об узле GraphLayout XML и о том, как добавить информацию с помощью сценария C#:

GraphLayout XML узел

Я пытался создайте консольное приложение, которое построило раздел макета XML и добавьте его в пакет. Но прежде чем показать код и эксперимент, я хотел бы проиллюстрировать некоторую информацию о Graphlayout XML.

Узел Graphlayout находится по следующему пути в XML:

DTS:DesignTimeProperties/Objects/Package/LayoutInfo/GraphLayout

Содержит проектную информацию обо всех объектах, добавленных в поток управления, даже в соединители с ограничениями предшествования. В этом XML узле вы можете найти три типа узлов (возможно, больше):

  1. NodeLayout: которые описывают задачи, например:

      <NodeLayout
      Size="151,42"
      Id="Package\Data Flow Task"
      TopLeft="369,179" />
    
  2. EdgeLayout: описывает соединители с ограничениями приоритета, и он более сложный, поскольку содержит всю информацию о кривых соединителей. Как пример:

    <EdgeLayout
      Id="Package.PrecedenceConstraints[Constraint]"
      TopLeft="308.5,125">
      <EdgeLayout.Curve>
        <mssgle:Curve
          StartConnector="{assembly:Null}"
          EndConnector="136,54"
          Start="0,0"
          End="136,46.5">
          <mssgle:Curve.Segments>
            <mssgle:SegmentCollection
              Capacity="5">
              <mssgle:LineSegment
                End="0,23" />
              <mssgle:CubicBezierSegment
                Point1="0,23"
                Point2="0,27"
                Point3="4,27" />
              <mssgle:LineSegment
                End="132,27" />
              <mssgle:CubicBezierSegment
                Point1="132,27"
                Point2="136,27"
                Point3="136,31" />
              <mssgle:LineSegment
                End="136,46.5" />
            </mssgle:SegmentCollection>
          </mssgle:Curve.Segments>
        </mssgle:Curve>
      </EdgeLayout.Curve>
      <EdgeLayout.Labels>
        <EdgeLabelCollection />
      </EdgeLayout.Labels>
    </EdgeLayout>
    
  3. AnnotationLayout: которые описывают аннотации. Например:

    <AnnotationLayout
      Text="This is an annotation"
      ParentId="Package"
      FontInfo="{assembly:Null}"
      Size="121,60"
      Id="edef7a97-4253-4bb8-907e-6079f42467c6"
      TopLeft="421,152" />
    

Эксперимент

Я создал консольное приложение, которое создает раздел DTS:DesignTimeProperties вручную, без добавления информации о соединителях ограничений приоритета (так как это сложно) . Я только попытался добавить информацию о двух задачах, имеющих следующие идентификаторы:

  1. Выполнить T- SQL Задача оператора
  2. Задача потока данных

Эти задачи были связаны с помощью соединителя ограничения приоритета.

Я использовал следующий код для изменения файла пакета .dtsx:

class Program
{
    static void Main(string[] args)
    {
        string package;
        string xmlLayout =  "  <DTS:DesignTimeProperties><![CDATA[<?xml version=\"1.0\"?>\r\n" +
                            "<!--This CDATA section contains the layout information of the package. The section includes information such as (x,y) coordinates, width, and height.-->\r\n" + 
                            "<!--If you manually edit this section and make a mistake, you can delete it. -->\r\n" +
                            "<!--The package will still be able to load normally but the previous layout information will be lost and the designer will automatically re-arrange the elements on the design surface.-->\r\n" +
                            "  <Objects\r\n" +
                            "  Version=\"8\">\r\n" +
                            "   <!--Each node below will contain properties that do not affect runtime behavior.-->\r\n" +
                             "  <Package\r\n" +
                            "    design-time-name=\"Package\">\r\n" +
                            "    <LayoutInfo>\r\n" +
                            "      <GraphLayout\r\n" +
                            "        Capacity=\"4\" xmlns=\"clr-namespace:Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization;assembly=Microsoft.SqlServer.IntegrationServices.Graph\" xmlns:mssgle=\"clr-namespace:Microsoft.SqlServer.Graph.LayoutEngine;assembly=Microsoft.SqlServer.Graph\" xmlns:assembly=\"http://schemas.microsoft.com/winfx/2006/xaml\">";


        xmlLayout += "\r\n" + AddNodeLayout("Execute T-SQL Statement Task", 193, 83);

        xmlLayout += "\r\n" + AddNodeLayout("Data Flow Task", 369, 179);

        xmlLayout += "\r\n" +   "      </GraphLayout>\r\n" +
                                "    </LayoutInfo>\r\n" +
                                "  </Package>\r\n" +
                                "</Objects>]]></DTS:DesignTimeProperties>\r\n";

        using (System.IO.StreamReader sr = new System.IO.StreamReader(@"G:\SSIS_Test\Integration Services Project1\Package3.dtsx"))
        {
            package = sr.ReadToEnd();
            sr.Close();
        }

        package = package.Substring(0, package.LastIndexOf("</DTS:Executable>")) +
            xmlLayout + package.Substring(package.LastIndexOf("</DTS:Executable>"));

        using (System.IO.StreamWriter sw = new System.IO.StreamWriter(@"G:\SSIS_Test\Integration Services Project1\Package3.dtsx"))
        {
            sw.Write(package);
            sw.Close();
        }
    }

    static string AddNodeLayout(string TaskId, int x, int y)
    {

        return "        <NodeLayout\r\n" +
      "          Size=\"225,42\"\r\n" +
      "          Id=\"Package\\" + TaskId + "\"\r\n" +
      "          TopLeft=\"" + x.ToString() + "," + y.ToString() + "\" />";


    }

}

Результаты и обсуждение

Раздел был добавлен успешно, но это не имеет смысла при открытии пакета в Visual Studio, поскольку задачи не были организованы, как описано (AutoLayout () был выполнен Visual Studio)

enter image description here

Я попытался удалить соединитель между обеими задачами и перезапустить эксперимент, задачи были организованы успешно:

enter image description here

Это означает, что если какой-либо макет объектов задач не определен, Visual Studio проигнорирует добавленный раздел и выполнит функцию AutoLayout () при открытии пакета.

На основании этого, если вы решили go При таком подходе (или даже при любом другом подходе) вы должны знать, как можно генерировать EdgeLayout узлы.


Обновление - поиск метода AutoLayout ()

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

После проверки сборок, импортированных в ваш проект, я провел небольшой поиск, используя Обозреватель объектов для метода AutoLayout(). Я думаю, что найдено два соответствующих метода:

  • Microsoft.SqlServer.IntegrationServices.Designer.View.BaseGraphControl.AutoLayout()
  • Microsoft.SqlServer.IntegrationServices.Designer.View.IGraphControlEx.AutoLayout()

Я не знаю, могут ли они быть выполнены из C# скрипт, так как они не принимают никаких аргументов. Я думаю, что они не созданы для использования из сценария C#, но являются внутренними методами для Visual studio. Но вы можете попробовать.

enter image description here

Примечание. По моему мнению, выполнение этого метода программно бесполезно, поскольку он будет выполняться Visual Studio после открытия пакета и не повлияет на выполнение пакета вообще

...