如何将CsvHelper记录添加到DataTable以用于SqlBulkCopy到数据库 [英] How to add CsvHelper records to DataTable to use for SqlBulkCopy to the database

查看:299
本文介绍了如何将CsvHelper记录添加到DataTable以用于SqlBulkCopy到数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用CsvHelper读取CSV文件,将每条记录加载到DataTable中,然后使用SqlBulkCopy将数据插入数据库表中.使用当前代码,将一行添加到DataTable时出现异常.例外是:无法将类型为'MvcStockAnalysis.Models.StockPrice'的对象强制转换为类型为'System.IConvertible'.无法存储在Date列中.预期的类型为DateTime."

I am trying to read a CSV file with CsvHelper, load each record into a DataTable, and then use SqlBulkCopy to insert the data into a database table. With the current code, I get an exception when adding a row to the DataTable. The exception is: "Unable to cast object of type 'MvcStockAnalysis.Models.StockPrice' to type 'System.IConvertible'.Couldn't store in Date Column. Expected type is DateTime."

示例CSV文件来自雅虎财经.例如:

The example CSV file is from yahoo finance. For example: http://ichart.yahoo.com/table.csv?s=MMM&a=0&b=1&c=2010&d=0&e=17&f=2014&g=d&ignore=.csv

CSV文件包含以下标题: 日期开盘高低开盘成交量调整

The CSV file contains the following header: Date Open High Low Close Volume Adj Close

我将CSV文件读取到的模型:

The model that I am reading the CSV file into:

namespace MvcStockAnalysis.Models
{
    using System;
    using System.Collections.Generic;

    public partial class StockPrice
    {
        public int Id { get; set; }
        public System.DateTime Date { get; set; }
        public int CompanyId { get; set; }
        public double High { get; set; }
        public double Low { get; set; }
        public double Close { get; set; }
        public double AdjClose { get; set; }
        public double Open { get; set; }
        public double Volume { get; set; }

        public virtual Company Company { get; set; }
    }
}

CSV文件到StockPrice类的映射使用以下内容:

The mapping of the CSV file to the StockPrice class uses the following:

public class StockPriceClassMap : CsvClassMap<StockPrice>
{
    public override void CreateMap()
    {
        Map(m => m.Date).Name("Date");
        Map(m => m.Close).Name("Close");
        Map(m => m.AdjClose).Name("Adj Close");
        Map(m => m.High).Name("High");
        Map(m => m.Low).Name("Low");
        Map(m => m.Open).Name("Open");
        Map(m => m.Volume).Name("Volume");
    }
}

试图将CsvHelper记录添加到DataTable的代码如下:

The code that tries to add the CsvHelper records to the DataTable is as follows:

var connectionstring = ConfigurationManager.ConnectionStrings["MvcStockAnalysis.Models.MvcStockAnalysisContext"];
var connection = new SqlConnection();
connection.ConnectionString = connectionstring.ToString();
var destinationTableName = "StockPrices";
var company = db.Company
            .Where(c => c.Symbol == "MMM")
            .FirstOrDefault();

try
{
    string path = HttpContext.Server.MapPath("~/App_Data/" + company.Symbol + @".csv");

    if (System.IO.File.Exists(path))
    {     

        using (StreamReader sr = new StreamReader(path))
        {
            using (var csv = new CsvReader(sr))
            {
                DataTable dt = new DataTable("StockPrices");
                csv.Configuration.HasHeaderRecord = true;
                csv.Configuration.RegisterClassMap<StockPriceClassMap>();

                dt.Columns.Add(new DataColumn("Date", typeof(DateTime)));
                dt.Columns.Add(new DataColumn("Close", typeof(Double)));
                dt.Columns.Add(new DataColumn("AdjClose", typeof(Double)));
                dt.Columns.Add(new DataColumn("High", typeof(Double)));
                dt.Columns.Add(new DataColumn("Low", typeof(Double)));
                dt.Columns.Add(new DataColumn("Open", typeof(Double)));
                dt.Columns.Add(new DataColumn("Volume", typeof(Double)));
                dt.Columns.Add(new DataColumn("CompanyId", typeof(Double)));
                var records = csv.GetRecords<StockPrice>().ToList();
                foreach (var record in records)
                {                                    
                    record.CompanyId = company.Id;
                    dt.Rows.Add(record);
                }
                // add dt to the database
                using (var bulkCopy = new SqlBulkCopy(connection.ConnectionString))
                {
                    // DataTable column names match my SQL Column names, so I simply made this loop. 
                    foreach (DataColumn col in dt.Columns)
                    {
                        bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
                    }
                    bulkCopy.DestinationTableName = destinationTableName;
                    bulkCopy.WriteToServer(dt);
                }
            }
        }
    }
    connection.Close();
}
catch (Exception e)
{
    Console.Write(e.Message);
}

如何将CsvHelper记录添加到DataTable中以用于SqlBulkCopy到数据库?

How can I add CsvHelper records to DataTable to use for SqlBulkCopy to the database?

推荐答案

我能够通过添加DataTable行并将其显式填充来实现此目的,而不必尝试将CsvHelper记录添加为一行.

I was able to get this to work by adding a DataTable row and filling it in explicitly, instead of trying to add a CsvHelper record as a row.

我用以下部分代替了上面显示的类似部分:

I used the following part instead of the similar part that is shown above:

foreach (var record in records)
{
    DataRow row = dt.NewRow();
    record.CompanyId = company.Id;
    row["Date"] = record.Date;
    row["Close"] = record.Close;
    row["AdjClose"] = record.AdjClose;
    row["High"] = record.High;
    row["Low"] = record.Low;
    row["Open"] = record.Open;
    row["Volume"] = record.Volume;
    row["CompanyId"] = record.CompanyId;
    dt.Rows.Add(row);
}

如果您无需花费太多精力就能解决问题,我将接受您的回答作为答案.

If you can solve the issue without so much hard coding, I will accept your answer as the answer.

这篇关于如何将CsvHelper记录添加到DataTable以用于SqlBulkCopy到数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆