在平面文件连接器上设置行分隔符属性

Posted

技术标签:

【中文标题】在平面文件连接器上设置行分隔符属性【英文标题】:Set row delimiter property on Flat File Connector 【发布时间】:2021-07-02 08:07:54 【问题描述】:

我正在创建一个允许我导入 CSV 的 BIML 脚本。

但是,平面文件连接管理器上的属性Row Delimiter 以某种方式设置为Vertical Bar,就像列分隔符一样。这会阻止我导入文件。

将列分隔符设置为垂直条,我只是不明白为什么它也将行分隔符设置为垂直条...

每当我手动将行分隔符设置为 CRLF 时,事情就像一个魅力。 但从 BIML 开始,它始终设置为与列分隔符相同的值。

我找不到发生这种情况的地方......

我尝试以多种方式使用表达式来设置行分隔符,但是唉.....

有人知道吗?

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <#
    string Applicatie = "BIML";
    string Prefix = "import";
     
    string fileName;
    string path = @"c:\temp";
    string[] myFiles = Directory.GetFiles(path, "*.csv");
     
    string[] myColumns;
    #>
    <FileFormats>
    <#
    foreach (string filePath in myFiles)
    
 
    #>
    <FlatFileFormat Name="FlatFileFormat<#=Path.GetFileNameWithoutExtension(filePath)#>" RowDelimiter="CRLF" ColumnNamesInFirstDataRow="true" IsUnicode="false">
        <Columns>
            <# 
                 
                StreamReader myFile = new StreamReader(filePath);
                myColumns = myFile.ReadLine().Replace("\"","").Split('|');
                 myFile.Close();
                 
                // to determine the column delimiter 
                int columnCount = 0;
                string columnDelimiter = "|";
 
                 foreach (string myColumn in myColumns) 
                
                    columnCount++;
                    if (columnCount == myColumns.Length)
                    
                        columnDelimiter = "CRLF";
                    
                    
                        columnDelimiter = "|";
                    
                #>
                <Column Name="<#=myColumn#>" DataType = "String" Length="250" Delimiter="<#=columnDelimiter#>"></Column>
                <#  #>
            </Columns>
        </FlatFileFormat>
            <##>
    </FileFormats>
    <Connections>
            <#
            foreach (string filePath in myFiles)
            
             
            #>
            <FlatFileConnection Name="FF_CSV-<#=Path.GetFileNameWithoutExtension(filePath)#>" 
                                FilePath="<#=filePath#>" 
                                FileFormat="FlatFileFormat<#=Path.GetFileNameWithoutExtension(filePath)#>" 
             >
                 <Expressions>
                    <Expression ExternalProperty="TextQualifier">&quot;\&quot;&quot;</Expression>
                    <Expression ExternalProperty="HeaderRowDelimiter">&quot;CRLF&quot;</Expression>
                    <Expression ExternalProperty="RowDelimiter">&quot;CRLF&quot;</Expression>
                </Expressions>

            </FlatFileConnection>
            <#  #>
            <OleDbConnection
                Name="STG_<#=Applicatie#>" 
                ConnectionString="Data Source=SQLSERVER;Initial Catalog=TEST;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;">
            </OleDbConnection>
                 <Connection ConnectionName="FF_CSV - <#=Path.GetFileNameWithoutExtension(filePath)#>">
                    <Expressions>
                        <Expression ExternalProperty="TextQualifier">&quot;\&quot;&quot;</Expression>
                        <Expression ExternalProperty="HeaderRowDelimiter">&quot;CRLF&quot;</Expression>
                        <Expression ExternalProperty="RowDelimiter">&quot;CRLF&quot;</Expression>
                    </Expressions>
                </Connection>
    </Connections> 
        <Packages>
 
    <#       // Loop trough the files
            int TableCount = 0;
            foreach (string filePath in myFiles)
             
                TableCount++;
                fileName = Path.GetFileNameWithoutExtension(filePath);
                #>
                <Package Name="stg_<#=Prefix#>_<#=TableCount.ToString()#>_<#=fileName#>" ConstraintMode="Linear" AutoCreateConfigurationsType="None" ProtectionLevel="EncryptSensitiveWithPassword" PackagePassword="secret">
                    <Variables>
                        <Variable Name="CountStage" DataType="Int32" Namespace="User">0</Variable>
                    </Variables>               
                    <Tasks>
                        <ExecuteSQL ConnectionName="STG_<#=Applicatie#>" Name="SQL - Truncate <#=fileName#>">
                            <DirectInput>TRUNCATE TABLE dbo.<#=Prefix#>_<#=fileName#></DirectInput>
                        </ExecuteSQL>
                         
                        <Dataflow Name="DFT-Transport CSV_<#=fileName#>">
                            <Transformations>
                                <FlatFileSource Name="SRC_FF-<#=fileName#> " ConnectionName="FF_CSV - <#=Path.GetFileNameWithoutExtension(filePath)#>">
                                </FlatFileSource>
                                 
                                <OleDbDestination ConnectionName="STG_<#=Applicatie#>" Name="OLE_DST - <#=fileName#>" >
                                <ExternalTableOutput Table="dbo.<#=Prefix#>_<#=fileName#>"/>
                                </OleDbDestination>
                            </Transformations>
                        </Dataflow>
                    </Tasks>
                </Package>
    <#        #>
 
                <!-- Create Master Package -->
                <Package Name="stg_<#=Prefix#>_0_Master" ConstraintMode="Parallel" AutoCreateConfigurationsType="None" ProtectionLevel="EncryptSensitiveWithPassword" PackagePassword="secret">
                    <Tasks>
                    <#  int TableCount2 = 0;
                        foreach (string filePath in myFiles)
                         
                                TableCount2++;
                                fileName = Path.GetFileNameWithoutExtension(filePath); #>
                 
                            <ExecutePackage Name="stg_<#=Prefix#>_<#=TableCount2.ToString()#>_<#=fileName#>">
                                <ExternalProjectPackage  Package="stg_<#=Prefix#>_<#=TableCount2.ToString()#>_<#=fileName#>.dtsx" />
                            </ExecutePackage>
                        <#
                        
                        #>    
                    </Tasks>
                </Package>
 
    </Packages>
</Biml>
 
<!--Includes/Imports for C#-->
<#@ template language="C#" hostspecific="true"#>
<#@ import namespace="System.Data"#>
<#@ import namespace="System.IO"#>

这是实际输出的 BIML:

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <Connections>
        <FlatFileConnection Name="FF_CSV - AB" FilePath="c:\temp\AB.csv" FileFormat="FlatFileFormatAB">
            <Expressions>
                <Expression ExternalProperty="TextQualifier">&quot;\&quot;&quot;</Expression>
                <Expression ExternalProperty="RowDelimiter">&quot;CRLF&quot;</Expression>
            </Expressions>
        </FlatFileConnection>
        <Connection Name="STG_BIML" ConnectionString="Data Source=SQLSERVER;Initial Catalog=TEST;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" />
    </Connections>
    <Packages>
        <Package Name="stg_import_1_AB" ConstraintMode="Linear" ProtectionLevel="EncryptSensitiveWithPassword" PackagePassword="secret">
            <Variables>
                <Variable Name="CountStage" DataType="Int32">0</Variable>
            </Variables>
            <Tasks>
                <ExecuteSQL Name="SQL - Truncate AB" ConnectionName="STG_BIML">
                    <DirectInput>TRUNCATE TABLE dbo.import_AB</DirectInput>
                </ExecuteSQL>
                <Dataflow Name="DFT - Transport CSV_AB">
                    <Transformations>
                        <FlatFileSource Name="SRC_FF - AB " ConnectionName="FF_CSV - AB" />
                        <OleDbDestination Name="OLE_DST - AB" ConnectionName="STG_BIML">
                            <ExternalTableOutput Table="dbo.import_AB" />
                        </OleDbDestination>
                    </Transformations>
                </Dataflow>
            </Tasks>
        </Package>
        <Package Name="stg_import_0_Master" ProtectionLevel="EncryptSensitiveWithPassword" PackagePassword="secret">
            <Tasks>
                <ExecutePackage Name="stg_import_1_AB">
                    <ExternalProjectPackage Package="stg_import_1_AB.dtsx" />
                </ExecutePackage>
            </Tasks>
        </Package>
    </Packages>
    <FileFormats>
        <FlatFileFormat Name="FlatFileFormatAB" ColumnNamesInFirstDataRow="true" RowDelimiter="CRLF" IsUnicode="false">
            <Columns>
                <Column Name="Relatienummer" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Tussenpersoon" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Polisnummer" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Subpakketpolisnummer" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Product" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Maatschappij" Length="250" DataType="String" Delimiter="|" />
                <Column Name="CodeVerzekering" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Branche" Length="250" DataType="String" Delimiter="|" />
                <Column Name="Termijn" Length="250" DataType="String" Delimiter="|" />
                <Column Name="SoortBedrijf" Length="250" DataType="String" Delimiter="|" />
                <Column Name="SBIcode" Length="250" DataType="String" Delimiter="|" />
                <Column Name="VerzekerdBedragA" Length="250" DataType="String" Delimiter="|" />
                <Column Name="VerzekerdBedragB" Length="250" DataType="String" Delimiter="|" />
            </Columns>
        </FlatFileFormat>
    </FileFormats>
</Biml>

【问题讨论】:

CSV 文件中的实际行分隔符是什么? 我假设为 FlatFileFormat 发出的 Biml 显示了所有列的管道字符?您可以将 9000 层级 biml 脚本添加到您的项目到 dump the raw biml 到文件中。另外,你的最后一栏有吗? @billinkc 确实如此。我为你添加了原始输出 【参考方案1】:

找到了

                if (columnCount == myColumns.Length)
                
                    columnDelimiter = "CRLF";
                
                
                    columnDelimiter = "|";
                

那里缺少else。应该是

                if (columnCount == myColumns.Length)
                
                    columnDelimiter = "CRLF";
                
                else
                
                    columnDelimiter = "|";
                

最少的复制

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<#
List<string> myColumns = new List<string>"A", "B", "C";

#>
<FileFormats>
    <FlatFileFormat Name="SO_66970366" RowDelimiter="CRLF" ColumnNamesInFirstDataRow="true" IsUnicode="false">
        <Columns>
<#
int columnCount = 0;
string columnDelimiter = "";
WriteLine($"<!-- ref count myColumns.Count -->");
    foreach(string myColumn in myColumns)
    
    
        columnCount++;
        bool finalColumn = columnCount == myColumns.Count;
        WriteLine($"<!-- actual count columnCount -->");
        WriteLine($"<!-- what columnCount == myColumns.Count finalColumn -->");
        
        if (finalColumn)
        
            columnDelimiter = "CRLF";
        
        else
        
            columnDelimiter = "|";
        
        WriteLine($"<!-- delimiter columnDelimiter -->");
        
#>
    <Column Name="<#=myColumn#>" DataType = "String" Length="250" Delimiter="<#=columnDelimiter#>" />
<#
    
#>            
        </Columns>
    </FlatFileFormat>
</FileFormats>    
        
</Biml>

发射的 Biml 看起来像

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
  <FileFormats>
    <FlatFileFormat Name="SO_66970366" RowDelimiter="CRLF" ColumnNamesInFirstDataRow="true" IsUnicode="false">
      <Columns>
        <!-- ref count 3 -->
        <!-- act count 1 -->
        <!-- what False False -->
        <!-- delimiter | -->
        <Column Name="A" DataType = "String" Length="250" Delimiter="|" />
        <!-- act count 2 -->
        <!-- what False False -->
        <!-- delimiter | -->
        <Column Name="B" DataType = "String" Length="250" Delimiter="|" />
        <!-- act count 3 -->
        <!-- what True True -->
        <!-- delimiter CRLF -->
        <Column Name="C" DataType = "String" Length="250" Delimiter="|" />
      </Columns>
    </FlatFileFormat>
  </FileFormats>
</Biml>

【讨论】:

Hmmmm.......错误:无法将方法组“计数”转换为非委托类型“对象”。您是否打算调用该方法? (29, 55) 在 C:\Users\hveijer\source\repos\migratie-BIML-importcsv\migratie-BIML-ImportCSV\30-transportdata.biml 哦,这就是你使用数组和我的列表的区别。将bool finalColumn = columnCount == myColumns.Count; 变成bool finalColumn = columnCount == myColumns.Length; 并不断提出 Biml 问题:D 学到了很多东西! 是是是!你是英雄! 2明天我将开始让这个“更智能”(配置表驱动)。所以这些问题将会出现:D

以上是关于在平面文件连接器上设置行分隔符属性的主要内容,如果未能解决你的问题,请参考以下文章

在 SSMS 中导入平面文件时的小数分隔符

在 SSMS 中导入平面文件时的小数分隔符

如何确保 BULK INSERT 将按顺序插入我的平面文件行?

数据服务 CSV 平面文件在列 [n] 之后应该有一个列分隔符

SSIS 包顽固的平面文件连接管理器

awk命令介绍