我试图用CsvHelper读取CSV文件,将每个记录加载到DataTable,然后使用sqlBulkCopy将数据插入数据库表.使用当前代码,在向DataTable添加行时会出现异常.例外情况是:“无法将’MvcStockAnalysis.Models.StockPrice’类型的对象强制转换为’System.IConvertible’.不能存储在日期列中.预期的类型是DateTime.”
示例CSV文件来自yahoo finance.例如: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文件读入的模型:
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; } } }
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的代码如下:
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); }
解决方法
如果我没弄错的话,你应该可以用更少的代码来做.在进入DataTable之前,您不必进入另一个类.
while( csv.Read() ) { var row = dt.NewRow(); foreach( DataColumn column in dt.Columns ) { row[column.ColumnName] = csv.GetField( column.DataType,column.ColumnName ); } dt.Rows.Add( row ); }