Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从编程生成的SSIS包中获取GraphLayout XML_C#_Sql Server_Ssis_Etl_Dts - Fatal编程技术网

C# 如何从编程生成的SSIS包中获取GraphLayout XML

C# 如何从编程生成的SSIS包中获取GraphLayout XML,c#,sql-server,ssis,etl,dts,C#,Sql Server,Ssis,Etl,Dts,如果在Visual Studio中打开SSIS DTSX包,设计器将创建一些附加的 数据包末尾CDATA块中的DesignTimeProperties 这看起来像

如果在Visual Studio中打开SSIS DTSX包,设计器将创建一些附加的 数据包末尾CDATA块中的DesignTimeProperties

这看起来像

<![CDATA[
....
问题是,只有在VisualStudio中打开包而在 集成服务项目

如果以编程方式使用
ManagedDTS
创建包,则此信息将丢失

我确实在
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);
然后通过

ControlFlowGraphModelElement controlFlowGraphModelElement = 
    new ControlFlowGraphModelElement();
controlFlowGraphModelElement.Initialize(package as IDTSSequence);
之后尝试通过

GraphModelElement graphModelElement = new GraphModelElement();
graphModelElement.Container = controlFlowGraphModelElement.Container;
var graphLayoutXml = SerializerHelper.Save(graphModelElement);    
显然我错过了一些安排。有人能帮我找到正确的方法吗

我知道
Microsoft.SqlServer.IntegrationServices.Graph.dll
中还有其他几个类,例如
Microsoft.SqlServer.Graph.dll
中的
LayoutGraph
GraphLayout
GraphControl
,但不幸的是 文档没有那么有用。

为什么它不起作用? 首先,我想从@Fredipux开始,这里有一些很棒的评论:

此GraphLayout结构描述Visual Studio SSIS Designer中的SSIS任务和组件布局及大小;该布局在包编辑期间定义。以编程方式生成包时,不会定义设计器布局,因为包是在VS Designer外部创建的

没错!!要点是
Microsoft.SqlServer.PipelineHost
Microsoft.SqlServer.DTSPipelineWrap
Microsoft.SqlServer.DTSRuntimeWrap
Microsoft.SqlServer.ManagedDTS
是.NET包装器,允许您在设计无意义的地方以编程方式创建和执行包。I如果您参考并浏览所有部分和子部分,您将注意到只提到这三个程序集,而未提及其他程序集,如Microsoft.SqlServer.IntegrationServices.Graph.dll,因为它们与Visual Studio设计器相关

您只需注意,上述四个程序集属于
Microsoft.SqlServer.Dts
命名空间,而另一个则属于
Microsoft.SqlServer.IntegrationServices

如何在VisualStudio中安排任务? 请注意,在VisualStudio中,可以在菜单条中转到

Format >> Auto Layout >> Diagram

在官方文档中,我搜索了ManagedDT和其他程序集列出的所有属性和方法,但没有发现您可以使用
AutoLayout()
方法。此外,即使使用ezApi和BIML,我也没有发现此选项可用

此外,我还尝试使用VisualStudio对象资源管理器搜索此方法,但没有成功

要试试吗 我认为添加布局最简单的方法是手动构建布局XML子句(从现有包中获取XML结构,并更改Id、大小和左上角属性),然后将其添加到包XML中

在运行了许多示例之后,看起来这是可能的,但是当有许多连接的任务时,这非常复杂。在下面的小节中,我演示了有关
GraphLayout
XML节点的一些有用信息,以及如何使用C#script添加信息:

图形布局XML节点 我试图创建一个控制台应用程序来构建布局XML部分并将其添加到包中,但是在展示代码和实验之前,我想说明一些关于GraphLayoutXML的信息

Graphlayout节点位于XML中的以下路径中:

DTS:DesignTimeProperties/Objects/Package/LayoutInfo/GraphLayout
它包含有关在控制流中添加的所有对象(甚至优先约束连接器)的设计信息。在此XML节点中,您可以找到三种类型的节点(可能更多):

  • NodeLayout:用于描述任务,例如:

      <NodeLayout
      Size="151,42"
      Id="Package\Data Flow Task"
      TopLeft="369,179" />
    
    <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>
    
    <AnnotationLayout
      Text="This is an annotation"
      ParentId="Package"
      FontInfo="{assembly:Null}"
      Size="121,60"
      Id="edef7a97-4253-4bb8-907e-6079f42467c6"
      TopLeft="421,152" />
    
    结果和讨论 该节已成功添加,但在Visual studio中打开包时没有意义,因为任务未按所述安排(AutoLayout()由Visual studio执行)

    我尝试移除两个任务之间的连接并重新运行实验,任务安排成功:

    这意味着,如果未定义任务对象的任何布局,Visual studio将忽略添加的部分,并在打开包时执行AutoLayout()函数。

    基于此,如果您决定使用此方法(甚至任何其他方法),您必须知道如何生成
    EdgeLayout
    节点


    更新-搜索AutoLayout()方法 根据您的评论,您不希望手动添加每个任务位置,但希望执行
    AutoLayout()
    方法

    检查项目中导入的程序集后,我使用对象资源管理器对
    AutoLayout()
    方法进行了一次小搜索。我认为找到了两种相关的方法:

    • Microsoft.SqlServer.IntegrationServices.Designer.View.BaseGraphControl.AutoLayout()
    • Microsoft.SqlServer.IntegrationServices.Designer.View.IGraphControlEx.AutoLayout()
    我不知道它们是否可以从C#脚本执行,因为它们不带任何参数。我认为它们不是为从C#脚本使用而构建的,但它们是Visual studio的内部方法。但您可以尝试一下

    注意:在我看来,以编程方式执行此方法是无用的,因为它会
    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() + "\" />";
    
    
        }
    
    }