首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从IDataReader (Fast )创建自定义类w/ LumenWorks,以便在有几个不同的文件版本时使用SqlBulkCopy?

如何从IDataReader (Fast )创建自定义类w/ LumenWorks,以便在有几个不同的文件版本时使用SqlBulkCopy?
EN

Stack Overflow用户
提问于 2013-07-23 23:37:00
回答 1查看 3.2K关注 0票数 2

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

经过相当一段时间的Google & MSDN搜索,我在http://www.michaelbowersox.com/2011/12/22/using-a-custom-idatareader-to-stream-data-into-a-database/批量插入Server数百万条记录上看到了这一点。

因为我使用的是LumenWorks快速CsvReader,我还没有弄清楚如何告诉CsvReader让IDataReader使用两个不同的字段版本。-( csvReader.FieldCount是这里的关键,但我看不出如何告诉CsvReader使用两个具有IDataReader接口的新类中的任何一个。请参阅下面的原始脚本和修改后的脚本..。谢谢..。

//原始剧本..。

代码语言:javascript
复制
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);
   }
}

//新剧本。

代码语言:javascript
复制
 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"); }
        );
   }
}

//示例脚本..。

代码语言:javascript
复制
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);
}
EN

回答 1

Stack Overflow用户

发布于 2013-07-24 00:09:58

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

*我假设,尽管有两种csv文件具有不同的字段顺序,但目标表是相同的。*编辑无需假设,您在评论中指出了这一点。

为了能够理解您的上下文,我从这里。获得了一些示例数据

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

代码语言:javascript
复制
Rk,Year,Age,Tm,Lg,Id,G,W,L,W-L,Finish,
1,1978,37,Atlanta Braves,NL,,162,69,93,.426,6

第二种类型,如(一些列被反转年龄<-> Finish,还有其他字段)

代码语言:javascript
复制
Rk,Year,Finish,Tm,Lg,Id,G,W,L,W-L,Age,Test1,Test2,Test3
1,1978,Very good year,Atlanta Braves,NL,,162,69,93,.426,96,,,,

因此目标表看起来类似于(只有列)

代码语言:javascript
复制
Rk,Year,Finish,Tm,Lg,Id,G,W,L,W-L,Age,Test1,Test2,Test3

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

选项1

  1. 添加步骤0,通过定义字段格式使所有输入文件在字段级别上统一。这可以通过创建与数据库中相同的字段来完成。

,假设Test4和Test5是目标表中存在的列,但在两个CSV文件中都缺少

代码语言:javascript
复制
Rk,Year,Finish,Tm,Lg,Id,G,W,L,W-L,Age,Test1,Test2,Test3,Test4,Test5
  1. 解析您拥有的所有文件(两种类型),根据您定义的格式,将它们重写到一个(或多个由您决定)上。这样,您只有一个(或多个)文件具有唯一的格式。
  2. 您现在可以解析这个文件,使用csv读取器将其插入数据库,因为字段不兼容问题是用您以唯一格式获得的最后一个文件来处理的。

选项2

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

代码语言:javascript
复制
            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个字段的文件重复相同的操作。

代码语言:javascript
复制
var FilesWith51Fields = Directory.GetFiles(@"D:\Data\51Fields", "*.csv");
......

关于SqlBulkCopyColumnMapping可以在这里找到的更多信息。

选项3

如果您想冒险创建数据读取器,下面是一些链接:

丹尼尔·韦瑟姆的博客

代码工程中的一个实例实现

另一个

最后是MSDN

个人注:由于时间不够,对于我的类似问题,我放弃了第三个选项,因为你需要做的所有单元测试和优化以及另一个调整,这可能需要时间(至少对我来说是这样)。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17822787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档