Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.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# 如何从LumenWorks(Fast CSV Reader)创建自定义类w/IDataReader,以便在具有多个不同文件版本的情况下使用SqlBulkCopy?_C#_Csv_Sqlbulkcopy_Idatareader - Fatal编程技术网

C# 如何从LumenWorks(Fast CSV Reader)创建自定义类w/IDataReader,以便在具有多个不同文件版本的情况下使用SqlBulkCopy?

C# 如何从LumenWorks(Fast CSV Reader)创建自定义类w/IDataReader,以便在具有多个不同文件版本的情况下使用SqlBulkCopy?,c#,csv,sqlbulkcopy,idatareader,C#,Csv,Sqlbulkcopy,Idatareader,由于内存问题,我决定将DataTable替换/转换为IDataReader 在谷歌和MSDN搜索了很长一段时间后,我在和遇到了这个问题 因为我正在使用LumenWorks Fast CSV Reader,我还不知道如何告诉CsvReader让IDataReader使用2个不同的字段版本:-(这里的关键是csvReader.FieldCount,但我不知道如何告诉csvReader使用具有IDataReader接口的两个新类中的任何一个。请参阅下面的原始脚本和修改的脚本…谢谢 //原始脚本 var

由于内存问题,我决定将DataTable替换/转换为IDataReader

在谷歌和MSDN搜索了很长一段时间后,我在和遇到了这个问题

因为我正在使用LumenWorks Fast CSV Reader,我还不知道如何告诉CsvReader让IDataReader使用2个不同的字段版本:-(这里的关键是csvReader.FieldCount,但我不知道如何告诉csvReader使用具有IDataReader接口的两个新类中的任何一个。请参阅下面的原始脚本和修改的脚本…谢谢

//原始脚本

var dbConnection = new SqlConnection(_dbConnectionString);

using (var dbBulkCopy = new SqlBulkCopy(dbConnection)
{
   using (CsvReader csvReader = new CsvReader(new StreamReader(filePath), false, '|', '"', '\\', '#', ValueTrimmingOptions.UnquoteOnly))
   {
       while(csvReader.ReadNextRecord())
       {
           if (csvReader.FieldCount == 48)
           {
               //Version 1...
               dataRow["DealerId"] = csvReader[0];
               dataRow["DealerName"] = csvReader[1];
               //Etc...
           }
           else if (csvReader.FieldCount == 51)
           {
               //Version 2...
               dataRow["DealerId"] = csvReader[0];
               dataRow["DealerName"] = csvReader[1];
               //Etc...
           }
           else { throw new Exception("Field Total Count Mismatched"); }

           dataTable.Rows.Add(dataRow);
       }

       dbConnection.Open();

       dbBulkCopy.WriteToServer(dataTable);
   }
}
//新脚本

 var dbConnection = new SqlConnection(_dbConnectionString);

using (var dbBulkCopy = new SqlBulkCopy(dbConnection)
{
   dbConnection.Open();

   using (CsvReader csvReader = new CsvReader(new StreamReader(filePath), false, '|', '"', '\\', '#', ValueTrimmingOptions.UnquoteOnly))
   {
       csvReader.ReadNextRecord();

       dbBulkCopy.WriteToServer(
           if (csvReader.FieldCount == 48)
           {
               //Version 1...

               csvReader....???  //Assign a custom class having IDataTable...
           }
           else if (csvReader.FieldCount == 51)
           {
               //Version 2...
               csvReader....???  //Assign a custom class having IDataTable...
           }
           else { throw new Exception("Field Total Count Mismatched"); }
        );
   }
}
//示例脚本

using (var file = new StreamReader(path))
using (var csv = new CsvReader(file, true)) // true = has header row
using (var bcp = new SqlBulkCopy(connection)) {
    bcp.DestinationTableName = "TableName";
    bcp.WriteToServer(csv);
}

因为,它会有点长,我写它作为一个答案

*我假设,尽管有两种csv文件以不同的字段顺序出现,但目标表是相同的* [编辑]您在评论中指出,无需假设

为了能够理解您的上下文,我从

假设第一种类型的文件如下所示:

Rk,Year,Age,Tm,Lg,Id,G,W,L,W-L,Finish,
1,1978,37,Atlanta Braves,NL,,162,69,93,.426,6
第二种类型类似(有些列是反转的,还有其他字段)

因此,目标表看起来类似(仅列)

我在这里看到两个选项(+1个选项):

选项1

  • 添加步骤0,通过定义字段格式,使所有输入文件在字段级别上保持一致。这可以通过在数据库上创建相同的字段来实现
  • [假设Test4和Test5是存在于目标表中但在两个CSV文件中都缺失的列]

    Rk,Year,Finish,Tm,Lg,Id,G,W,L,W-L,Age,Test1,Test2,Test3,Test4,Test5
    
  • 解析您拥有的所有文件(两种类型)并根据您定义的格式将其重写到一个(或多个)文件上。这样,您只有一个(或多个)具有唯一格式的文件

  • 您现在可以使用csv阅读器解析此文件以将其插入数据库,因为字段不兼容问题是用您以唯一格式获得的最后一个文件处理的

  • 选项2

    您将执行SqlBulkCopy操作两次。第一轮您将读取有48个字段的文件,下一轮您将读取有51个字段的文件

                var FilesWith48Fields = Directory.GetFiles(@"D:\Data\48Fields", "*.csv");
    
                foreach (var fileName in FilesWith48Fields)
                {
                    using (var file = new StreamReader(fileName))
                    using (var csv = new CsvReader(file, true)) // true = has header row
                    using (var bcp = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepNulls))
                    {
                        bcp.DestinationTableName = "fletchsodTable";
                        // map the first field of your CSV to the column in Database
                        var mapping1 = new SqlBulkCopyColumnMapping(0, "FirstColumnName");
                        bcp.ColumnMappings.Add(mapping1);
    
                        var mapping2 = new SqlBulkCopyColumnMapping(1, "SecondColumnName");
                        bcp.ColumnMappings.Add(mapping2);  
                        ....
    
                        bcp.WriteToServer(csv);
                    }
                }
    
    并对具有51个字段的文件重复相同的操作

    var FilesWith51Fields = Directory.GetFiles(@"D:\Data\51Fields", "*.csv");
    ......
    
    有关的更多信息

    选项3

    如果您想在创建数据读取器的过程中冒险,以下是一些链接:

    个人备忘 由于缺乏时间,对于我的一个类似问题,我放弃了第三个选项,因为所有的单元测试和优化,你必须做和其他调整,这可能需要时间(至少对我来说,是这样的)

    选项4
    也许,使用我在选项2中指出的列映射,您可能希望通过测试字段计数来实现您的方法。但出于本能,我建议不要使用硬编码整数来计算字段。

    我建议您查看@。将csv读取到数据表,然后插入它们可能会很痛苦。对于您的特定情况,我曾经有过一个类似的例子ar问题。我收到的csv文件格式不统一。因此,我在所有其他处理之前添加了一个步骤0,该步骤包括删除格式不正确的行和/或正确重新设置格式[您甚至可以拆分文件以创建2:一个用于48个字段,另一个用于51个字段]。然后使用sqlbulkcopy您可以轻松地传输数据。我添加了“示例脚本”来自提供的web链接的代码。我不确定您所指的步骤0是什么。假设我在一个文件夹中有23个文件,每个文件在循环中一次运行一个。13个文件有48个字段,10个文件在所有行上有51个字段。数据库表有51个字段。我没有问题w/51字段平面文件,但48个字段fla我不知道如何告诉IDataReader类为4个缺少的字段使用默认值。我写了一个答案,因为注释不能提供足够的位置。
                var FilesWith48Fields = Directory.GetFiles(@"D:\Data\48Fields", "*.csv");
    
                foreach (var fileName in FilesWith48Fields)
                {
                    using (var file = new StreamReader(fileName))
                    using (var csv = new CsvReader(file, true)) // true = has header row
                    using (var bcp = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepNulls))
                    {
                        bcp.DestinationTableName = "fletchsodTable";
                        // map the first field of your CSV to the column in Database
                        var mapping1 = new SqlBulkCopyColumnMapping(0, "FirstColumnName");
                        bcp.ColumnMappings.Add(mapping1);
    
                        var mapping2 = new SqlBulkCopyColumnMapping(1, "SecondColumnName");
                        bcp.ColumnMappings.Add(mapping2);  
                        ....
    
                        bcp.WriteToServer(csv);
                    }
                }
    
    var FilesWith51Fields = Directory.GetFiles(@"D:\Data\51Fields", "*.csv");
    ......