I've written a method, BulkCopy, to upload my Excel file to SQL Server database table. I am trying to unit test this and it fails each time with "System.NotSupportedException : Specified method is not supported".
If someone could have a look it would be much appreciated.
Kind regards,
Emmett
public static void BulkCopy(string inputFilePath, string tableName)
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var stream = File.Open(inputFilePath, FileMode.Open, FileAccess.Read);
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
using (var bulkCopy = new SqlBulkCopy(ConnectionString))
{
bulkCopy.EnableStreaming = true;
bulkCopy.DestinationTableName = tableName;
reader.Read();
var cols = Enumerable.Range(0, reader.FieldCount).Select(i => reader.GetValue(i)).ToArray();
foreach (var col in cols)
{
var column = cols.GetValue(0).ToString();
if (column.Trim() == "Column 1")
{
bulkCopy.ColumnMappings.Add(column, "Column 1");
}
if (column.Trim() == "Column 2")
{
bulkCopy.ColumnMappings.Add(column, "Column 2");
}
if (column.Trim() == "Column 3")
{
bulkCopy.ColumnMappings.Add(column, "Column 3");
}
//continued for column mappings...
}
bulkCopy.WriteToServer(reader);
}
Console.WriteLine("Copy data to database done (DataReader).");
}
}
I tested your code ,the issue is showed in the following code ,you reader is incorrect.
bulkCopy.WriteToServer(reader);
Pass the datatable into bulk , try the below code
public static void BulkCopy(string inputFilePath, string tableName)
{
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var stream = System.IO.File.Open(inputFilePath, FileMode.Open, FileAccess.Read);
IExcelDataReader reader;
if (inputFilePath.EndsWith(".xls"))
reader = ExcelReaderFactory.CreateBinaryReader(stream);
else if (inputFilePath.EndsWith(".xlsx"))
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
else
throw new Exception("The file to be processed is not an Excel file");
var conf = new ExcelDataSetConfiguration
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
UseHeaderRow = true
}
};
var dataSet = reader.AsDataSet(conf);
// Now you can get data from each sheet by its index or its "name"
var dataTable = dataSet.Tables[0];
using (var bulkCopy = new SqlBulkCopy(ConnectionString))
{
bulkCopy.EnableStreaming = true;
bulkCopy.DestinationTableName = tableName;
reader.Read();
var cols = Enumerable.Range(0, reader.FieldCount).Select(i => reader.GetValue(i)).ToArray();
foreach (var col in cols)
{
var column =col.ToString();
if (column.Trim() == "Column 1")
{
bulkCopy.ColumnMappings.Add(column, "Column1");
}
if (column.Trim() == "Column 2")
{
bulkCopy.ColumnMappings.Add(column, "Column2");
}
if (column.Trim() == "Column 3")
{
bulkCopy.ColumnMappings.Add(column, "Column3");
}
//continued for column mappings...
}
bulkCopy.WriteToServer(dataTable);
}
Console.WriteLine("Copy data to database done (DataReader).");
}
Pass the dataReader into bulk, change your foreach
part as shown
for (var i = 0; i<cols.Count();i++)
{
if (cols[i].ToString().Trim() == "Column 1")
{
bulkCopy.ColumnMappings.Add(i, "Column1");
}
if (cols[i].ToString().Trim() == "Column 2")
{
bulkCopy.ColumnMappings.Add(i, "Column2");
}
if (cols[i].ToString().Trim() == "Column 3")
{
bulkCopy.ColumnMappings.Add(i, "Column3");
}
//continued for column mappings...
}