BIML数据流无法读取配置文件

时间:2018-05-30 10:12:48

标签: ssis dataflow biml

摘要

配置文件查找适用于执行SQL任务,但对于数据流任务失败。

问题

我有2个数据库:

  1. 源(内部部署SQL Server数据库)
  2. 目标(Azure SQL数据库)
  3. 我想从BIML代码创建2个包。

    1)创建分段(工作正常)

    • 使用每个循环和源数据库中的元数据
    • 在目标数据库中创建表

    2)加载分段(不起作用)

    • 使用每个循环和数据流任务(源到目标)
    • 在目标数据库中加载已创建的表

    这两个软件包都需要使用我创建的软件包配置文件,该文件存储目标数据库的用户名和密码(Azure数据库,使用SQL Server身份验证)。

    使用此配置文件适用于包1),但是当我尝试使用包2的BIML代码创建SSIS包时)我收到以下错误:

    Could not execute Query on Connection Dest: SELECT * FROM stg.SalesTaxRate. Login failed for user ''.
    

    我已尝试使用BIML Code for Package 1)并添加数据流任务并且似乎引发了同样的错误 - 似乎在使用执行SQL任务时它可以找到并使用配置文件没问题,但是使用数据流任务时,它无法找到它。

    包1的脚本):

    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ template language="C#" tier="2" #>
    <#
        string _source_con_string = @"Data Source=YRK-L-101098;Persist Security Info=true;Integrated Security=SSPI;Initial Catalog=AdventureWorks2016";
        string _dest_con_string = @"Data Source=mpl.database.windows.net;Initial Catalog=mpldb;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False";
    
        string _table_name_sql = "SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"; 
    
        DataTable _table_names = new DataTable();
        SqlDataAdapter _table_name_da = new SqlDataAdapter(_table_name_sql, _source_con_string);
        _table_name_da.Fill(_table_names);  
    
    #>
    <#+ 
    public string RowConversion(DataRow Row)
    {
        string _ret = "[" + Row["COLUMN_NAME"] + "] " + Row["DATA_TYPE"];
    
    
        switch (Row["DATA_TYPE"].ToString().ToUpper())
        {
            case "NVARCHAR":
            case "VARCHAR":
            case "NCHAR":
            case "CHAR":
            case "BINARY":
            case "VARBINARY":
                if (Row["CHARACTER_MAXIMUM_LENGTH"].ToString() == "-1")
                    _ret += "(max)";
                else
                    _ret += "(" + Row["CHARACTER_MAXIMUM_LENGTH"] + ")";
                break;
    
            case "NUMERIC":
                _ret += "(" + Row["NUMERIC_PRECISION"] + "," + Row["NUMERIC_SCALE"] + ")";
                break;
    
            case "FLOAT":
                _ret += "(" + Row["NUMERIC_PRECISION"] + ")";
                break;
        }
    
        return _ret;
    }
    #> 
    
    <Biml xmlns="http://schemas.varigence.com/biml.xsd">
      <Connections>
        <OleDbConnection Name="Dest" ConnectionString="Data Source=mpl.database.windows.net;Initial Catalog=mpldb;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False" /> 
      </Connections>
        <Packages>
            <Package Name="005_Create_Staging_Configuration" ConstraintMode="Linear">
    
                <PackageConfigurations>
                    <PackageConfiguration Name="Configuration">
                        <ExternalFileInput ExternalFilePath="C:\VSRepo\BIML\Configurations\AzureConfigEdit.dtsConfig">
                        </ExternalFileInput>
                    </PackageConfiguration>
                </PackageConfigurations>
    
                <Tasks>
                <Container Name="Create Staging Tables" ConstraintMode="Linear">
                    <Tasks>
                        <# foreach(DataRow _table in _table_names.Rows) {    #>           
                        <ExecuteSQL Name="SQL-S_<#= _table["TABLE_NAME"] #>" ConnectionName="Dest">
                            <DirectInput>
    
                                IF OBJECT_ID('stg.<#= _table["TABLE_NAME"] #>','U') IS NOT NULL
                                DROP TABLE stg.<#= _table["TABLE_NAME"] #>;
    
                                CREATE TABLE stg.<#= _table["TABLE_NAME"] #>
                                (
                                <#
    
                                    string _col_name_sql = "select COLUMN_NAME, DATA_TYPE,  CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='" + _table["TABLE_SCHEMA"] + "' and TABLE_NAME='"+ _table["TABLE_NAME"] + "' order by ORDINAL_POSITION ";
    
                                    DataTable _col_names = new DataTable();
                                    SqlDataAdapter _col_names_da = new SqlDataAdapter(_col_name_sql, _source_con_string);
                                    _col_names_da.Fill(_col_names);
    
                                    for (int _i=0; _i<_col_names.Rows.Count ; _i++  )
                                    {
                                        DataRow _r = _col_names.Rows[_i];
    
                                        if (_i == 0)
                                            WriteLine(RowConversion(_r));
                                        else
                                            WriteLine(", " + RowConversion(_r));                                
                                    }
    
                                #>
                                , append_dt datetime
                                )
                            </DirectInput>
                        </ExecuteSQL>
                        <# } #>
                    </Tasks>
                </Container>
                </Tasks>        
            </Package>
        </Packages>
    </Biml>
    

    包2的脚本)

    <#@ import namespace="System.Data" #>
    <#@ import namespace="System.Data.SqlClient" #>
    <#@ template language="C#" tier="2" #>
    <#
        string _source_con_string = @"Data Source=YRK-L-101098;Persist Security Info=true;Integrated Security=SSPI;Initial Catalog=AdventureWorks2016";
        string _dest_con_string = @"Data Source=mpl.database.windows.net;Initial Catalog=mpldb;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False";
    
        string _table_name_sql = "select  TABLE_SCHEMA , table_name from INFORMATION_SCHEMA.TABLES  where TABLE_TYPE='BASE TABLE'"; 
    
        DataTable _table_names = new DataTable();
        SqlDataAdapter _table_name_da = new SqlDataAdapter(_table_name_sql, _source_con_string);
        _table_name_da.Fill(_table_names);  
    
    #>
    
    <Biml xmlns="http://schemas.varigence.com/biml.xsd">
      <Connections>
        <OleDbConnection Name="Source" ConnectionString="Data Source=YRK-L-101098;Provider=SQLNCLI11.1;Persist Security Info=true;Integrated Security=SSPI;Initial Catalog=AdventureWorks2016" />
        <OleDbConnection Name="Dest" ConnectionString="Data Source=mpl.database.windows.net;Initial Catalog=mpldb;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False" />
      </Connections>
        <Packages>
            <Package Name="006_Load_Staging_Configuration" ConstraintMode="Linear">
                <PackageConfigurations>
                    <PackageConfiguration Name="Configuration">
                        <ExternalFileInput ExternalFilePath="C:\VSRepo\BIML\Configurations\AzureConfigDF.dtsConfig"></ExternalFileInput>
                    </PackageConfiguration>
                </PackageConfigurations>
                <Tasks>
                <Container Name="Load Staging Tables" ConstraintMode="Linear">
                    <Tasks>
                        <# foreach(DataRow _table in _table_names.Rows) {    #>     
                        <Dataflow Name="DFT-S_<#= _table["TABLE_NAME"] #>">
                            <Transformations>
                                <OleDbSource Name="SRC-<#= _table["TABLE_SCHEMA"] #>_<#= _table["TABLE_NAME"] #>" ConnectionName="Source">
                                    <DirectInput>
                                        SELECT  *
                                        FROM <#= _table["TABLE_SCHEMA"] #>.<#= _table["TABLE_NAME"] #>
                                    </DirectInput>
                                </OleDbSource>
                                <OleDbDestination Name="DST-<#= _table["TABLE_SCHEMA"] #>_<#= _table["TABLE_NAME"] #>" ConnectionName="Dest">
                                    <ExternalTableOutput Table="stg.<#= _table["TABLE_NAME"] #>"/>
                                </OleDbDestination>
                            </Transformations>
                        </Dataflow>
                        <# } #>
                    </Tasks>
                </Container>
                </Tasks>        
            </Package>
        </Packages>
    </Biml>
    

    配置文件:

    <?xml version="1.0"?>
    <DTSConfiguration>
      <Configuration ConfiguredType="Property" Path="\Package.Connections[Source].Properties[ConnectionString]" ValueType="String">
        <ConfiguredValue>"Data Source=YRK-L-101098;Provider=SQLNCLI11.1;Persist Security Info=true;Integrated Security=SSPI;Initial Catalog=AdventureWorks2016"</ConfiguredValue>
      </Configuration>  <Configuration ConfiguredType="Property" Path="\Package.Connections[Dest].Properties[ConnectionString]" ValueType="String">
        <ConfiguredValue>Data Source=mpl.database.windows.net;User ID=*****;Initial Catalog=mpldb;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False</ConfiguredValue>
      </Configuration>
      <Configuration ConfiguredType="Property" Path="\Package.Connections[Dest].Properties[Password]" ValueType="String">
        <ConfiguredValue>******</ConfiguredValue>
      </Configuration>
      <Configuration ConfiguredType="Property" Path="\Package.Connections[Dest].Properties[UserName]" ValueType="String">
        <ConfiguredValue>******</ConfiguredValue>
      </Configuration>
    </DTSConfiguration>
    

    注意:&#39; UserId&#39;的值和密码&#39;在实际脚本中填充了正确的值。

1 个答案:

答案 0 :(得分:2)

<强>摘要
问题是,在使用Biml(构建时功能)生成包时,您正在尝试使用包配置(SSIS运行时功能)。

发生了什么事?
这样想吧。如果要在开发期间手动创建SSIS包,则必须通过指定用户名和密码来连接到源数据库和目标数据库。如果不连接数据库,SSIS将无法获取所需的元数据。一旦开发了包并且已映射了所有元数据,就可以使用包配置。当您打开或执行包配置包时,所有硬编码值都将被配置值替换。此值替换是SSIS运行时功能。

现在,将其与使用Biml进行比较,而不是手动创建SSIS包:生成包时,您期望Biml引擎从包配置文件中获取用户名和密码。由于这是SSIS运行时功能,因此Biml无法获取该数据,并将使用BimlScript中指定的连接字符串。由于这些连接字符串未指定用户名和密码,因此Biml将无法连接,并且您收到错误用户'的登录失败。 (这类似于在SSIS中创建连接管理器而不提供用户名和密码,并在单击“测试连接”时收到错误。)

但它适用于执行SQL任务吗?
它可能看起来像,但它没有。执行SQL任务基本上只是被忽略了。在执行包之前,SSIS或Biml引擎不会检查或验证执行SQL任务中的SQL代码。你可以在那里输入任何内容,SSIS会很高兴,直到你尝试执行无效的代码,此时它会给你一个错误。由于SSIS在开发期间未对此代码进行验证,因此Biml在包生成期间不会对其进行验证。包成功生成,然后当您打开它时,将应用包配置,您将看不到任何错误。

然而,OLE DB目标在开发期间由SSIS和Biml引擎验证。他们都需要连接到数据库才能获取元数据。这就是您仅在此文件中出现错误的原因。

<强>解决方案
程序包配置仅适用于SSIS运行时功能。您不能使用它们将连接字符串,用户名或密码传递给Biml引擎。您既可以对BimlScript中的连接字符串进行硬编码,也可以将连接字符串存储在外部元数据存储库中,但是在生成包时,您需要向Biml引擎提供用户名和密码。