using System.Collections.Generic;
using System.Diagnostics;
using System.Data.SqlClient;
public class CsvReader : IDataReader
private readonly char CSV_DELIMITER = ',';
private readonly StreamReader _sr;
private readonly Dictionary<string, Func<string, object>> _csv2SqlType;
private readonly string[] _headers;
private string[] _values;
public int FieldCount { get { return _headers.Length; } }
public CsvReader(string filePath, Dictionary<string, Func<string, object>> csvColumn2SqlTypeDict)
if (string.IsNullOrEmpty(filePath))
throw new ArgumentException("is null or empty", "filePath");
if (!System.IO.File.Exists(filePath))
throw new IOException(string.Format("{0} doesn't exist or access denied", filePath));
if (csvColumn2SqlTypeDict == null)
throw new ArgumentNullException("csvColumn2SqlTypeDict");
_sr = new StreamReader(filePath);
_csv2SqlType = csvColumn2SqlTypeDict;
_headers = ReadHeaders();
public object GetValue(int i)
var colValue = _values[i];
var colName = _headers[i];
try { return _csv2SqlType[colName](colValue); }
if (_sr.EndOfStream) return false;
_values = _line.Split(CSV_DELIMITER);
if (_values.Length != _headers.Length)
private void ValidateHeaders()
if (_headers.Length != _csv2SqlType.Keys.Count)
throw new InvalidOperationException(string.Format("Read {0} columns, but csv2SqlTypeDict contains {1} columns", _headers.Length, _csv2SqlType.Keys));
foreach (var column in _headers)
if (!_csv2SqlType.ContainsKey(column))
throw new InvalidOperationException(string.Format("There is no convertor for column '{0}'", column));
private string[] ReadHeaders()
var headerLine = _sr.ReadLine();
if (string.IsNullOrEmpty(headerLine))
throw new InvalidDataException("There is no header in CSV!");
var headers = headerLine.Split(CSV_DELIMITER);
throw new InvalidDataException("There is no header in CSV after Split!");
public object this[string name]
throw new NotImplementedException();
public object this[int i]
throw new NotImplementedException();
throw new NotImplementedException();
throw new NotImplementedException();
public int RecordsAffected
throw new NotImplementedException();
throw new NotImplementedException();
public bool GetBoolean(int i)
throw new NotImplementedException();
public byte GetByte(int i)
throw new NotImplementedException();
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
throw new NotImplementedException();
public char GetChar(int i)
throw new NotImplementedException();
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
throw new NotImplementedException();
public IDataReader GetData(int i)
throw new NotImplementedException();
public string GetDataTypeName(int i)
throw new NotImplementedException();
public DateTime GetDateTime(int i)
throw new NotImplementedException();
public decimal GetDecimal(int i)
throw new NotImplementedException();
public double GetDouble(int i)
throw new NotImplementedException();
public Type GetFieldType(int i)
throw new NotImplementedException();
public float GetFloat(int i)
throw new NotImplementedException();
public Guid GetGuid(int i)
throw new NotImplementedException();
public short GetInt16(int i)
throw new NotImplementedException();
public int GetInt32(int i)
throw new NotImplementedException();
public long GetInt64(int i)
throw new NotImplementedException();
public string GetName(int i)
throw new NotImplementedException();
public int GetOrdinal(string name)
throw new NotImplementedException();
public DataTable GetSchemaTable()
throw new NotImplementedException();
public string GetString(int i)
throw new NotImplementedException();
public int GetValues(object[] values)
throw new NotImplementedException();
public bool IsDBNull(int i)
throw new NotImplementedException();
throw new NotImplementedException();
#endregion Not neccesarry
public static void Main(string[] args)
var csvColumn2SqlTypeDict = new Dictionary<string, Func<string, object>>
{ "int", (s) => Convert.ToInt32(s) },
{ "double", (s) => Convert.ToDouble(s) },
{ "date", (s) => Convert.ToDateTime(s) },
Stopwatch sw = Stopwatch.StartNew();
using (var csvReader = new CsvReader("example.csv", csvColumn2SqlTypeDict))
var cs = @"Server=localhost\SQLEXPRESS;initial catalog=TestDb;Integrated Security=true";
using (var loader = new SqlBulkCopy(cs, SqlBulkCopyOptions.Default))
loader.DestinationTableName = "Test";
loader.WriteToServer(csvReader);
Console.WriteLine("Got an exception: {0}", ex);
Console.WriteLine("Press 'Enter' to quit");
Console.WriteLine("Data has been written in {0}", sw.Elapsed);
Console.WriteLine("Press 'Enter' to quit");
private static void ShowCsv(IDataReader dr)
Console.WriteLine("Row# {0}", i);
for (int j = 0; j < dr.FieldCount; j++)
Console.WriteLine("{0} => {1}", j, dr.GetValue(j));