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

BIML Dataflow fails to read Configuration file

总结

配置文件查找对执行 SQL 任务有效,但对数据流任务无效。

问题

我有 2 个数据库:

  1. 来源(本地 SQL 服务器数据库)
  2. 目标(Azure SQL 数据库)

我想从 BIML 代码创建 2 个包。

1) 创建登台(工作正常)

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

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

使用此配置文件可以很好地用于包 1),但是当我尝试使用 BIML 代码为包 2) 创建 SSIS 包时,出现以下错误:

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

我已经尝试使用包 1) 的 BIML 代码并添加数据流任务,这似乎引发了同样的错误 - 似乎在使用执行 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>

注意:'UserId'和'Password'的值在实际脚本中填充了正确的值。

总结
问题是您在通过使用 Biml(构建时功能)生成包来开发包时尝试使用包配置(SSIS 运行 时功能)。

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

现在,将其与使用 Biml 而不是手动创建 SSIS 包进行比较:生成包时,您希望 Biml 引擎从包配置文件中获取用户名和密码。由于这是一个 SSIS 运行-time 功能,Biml 无法获取该数据,并将使用 BimlScript 中指定的连接字符串。由于这些连接字符串未指定用户名和密码,因此 Biml 将无法连接并且您会收到错误 Login failed for user ''。 (这类似于在没有提供用户名和密码的情况下在 SSIS 中创建连接管理器并在单击 "Test Connection" 时出现错误。)

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

但是,OLE DB 目标在开发过程中由 SSIS 和 Biml 引擎验证。他们都需要连接到数据库以获取元数据。这就是为什么你只在这个文件上得到错误。

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