SQL Bulk Insert Problem while inserting excel data

Cenk 1,036 Reputation points
2023-01-18T11:41:22.24+00:00

Hi guys,

In my Blazor Server application, I am trying to insert excel data into a SQL database table. I am getting this error, but couldn't figure out why. Hope you can help me.

Error:

The given ColumnName 'PID' does not match up with any column in data source.

Here is the sample excel, I am trying to bulk insert.

Ekran görüntüsü 2023-01-18 144031

CREATE TABLE [dbo].[RazerReconciliation](
	[PID] [nvarchar](50) NULL,
	[ProductName] [nvarchar](200) NULL,
	[ProductAmount] [float] NULL,
	[ReferenceNo] [uniqueidentifier] NOT NULL,
	[Quantity] [int] NOT NULL
) ON [PRIMARY]
GO
public async Task UploadReconciliationFile(IFormFile file)
    {
        var untrustedFileName = file.FileName;
        
       
        try
        {
            var path = Path.Combine(env.ContentRootPath,
                env.EnvironmentName, "unsafe_uploads",
                untrustedFileName);

            await using FileStream fs = new(path, FileMode.Create);
            await file.CopyToAsync(fs);

            logger.LogInformation("{untrustedFileName} saved at {Path}",
                untrustedFileName, path);
            
            var sqlConnectionString = configuration["ConnectionStrings:DefaultConnection"];

            // Get the datatable from procedure on Utility.cs page
            var datapush = Utility.Utility.ImportToDataTable(path, "Sheet1");

            // open connection to sql and use bulk copy to write excelData to my table
            await using var destinationConnection = new SqlConnection(sqlConnectionString);
            destinationConnection.Open();
            using var bulkCopy = new SqlBulkCopy(destinationConnection);
            bulkCopy.DestinationTableName = "RazerReconciliation";
            bulkCopy.ColumnMappings.Add("PID", "PID");
            bulkCopy.ColumnMappings.Add("ProductName", "ProductName");
            bulkCopy.ColumnMappings.Add("ProductAmount", "ProductAmount");
            bulkCopy.ColumnMappings.Add("ReferenceNo", "ReferenceNo");
            bulkCopy.ColumnMappings.Add("Quantity", "Quantity");
            await bulkCopy.WriteToServerAsync(datapush);
        }
        catch (Exception ex)
        {
            logger.LogError("{untrustedFileName} error on upload (Err: 3): {Message}",
                untrustedFileName, ex.Message);

        }
    }


public class Utility
    {
        public static DataTable ImportToDataTable(string filePath, string sheetName)
        {
            var dt = new DataTable();
            var fi = new FileInfo(filePath);
            // Check if the file exists
            if (!fi.Exists)
                throw new Exception("File " + filePath + " Does Not Exists");

            // If you use EPPlus in a noncommercial context
            // according to the Polyform Noncommercial license:
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using var xlPackage = new ExcelPackage(fi);
            // get the first worksheet in the workbook
            var worksheet = xlPackage.Workbook.Worksheets[sheetName];

            // Fetch the WorkSheet size
            ExcelCellAddress startCell = worksheet.Dimension.Start;
            ExcelCellAddress endCell = worksheet.Dimension.End;

            // create all the needed DataColumn
            for (var col = startCell.Column; col <= endCell.Column; col++)
                dt.Columns.Add(col.ToString());

            // place all the data into DataTable
            for (var row = startCell.Row; row <= endCell.Row; row++)
            {
                DataRow dr = dt.NewRow();
                int x = 0;
                for (int col = startCell.Column; col <= endCell.Column; col++)
                {
                    dr[x++] = worksheet.Cells[row, col].Value;
                }

                dt.Rows.Add(dr);
            }

            return dt;
        }
    }
Developer technologies .NET Entity Framework Core
Developer technologies .NET Blazor
SQL Server Other
Developer technologies C#
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Naimish Makwana 175 Reputation points
    2023-01-18T16:34:49.64+00:00

    Hello @cenk

    Your ImportToDataTable method return wrong Column name in Datatable. EX: 1,2,3,4,5,

    and PID, ProductName and other column is consider as Row data. Which is wrong and create the issue while ColumnMappings.

    DataTable

    Replace your Utility class to

    public class Utility
    {
        public static DataTable ImportToDataTable(string filePath, string sheetName, bool hasHeader = true)
        {
            var dt = new DataTable();
            var fi = new FileInfo(filePath);
            // Check if the file exists
            if (!fi.Exists)
                throw new Exception("File " + filePath + " Does Not Exists");
    
            // If you use EPPlus in a noncommercial context
            // according to the Polyform Noncommercial license:
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using var xlPackage = new ExcelPackage(fi);
            // get the first worksheet in the workbook
            var worksheet = xlPackage.Workbook.Worksheets[sheetName];
    
            // create all the needed DataColumn
            foreach (var firstRowCell in worksheet.Cells[1, 1, 1, worksheet.Dimension.End.Column])
            {
                
     if (firstRowCell.Text == "ReferenceNo")
                    {
                        dt.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column), typeof(Guid));
                    }
                    else
                    {
                        dt.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
                    }
            }
    
            var startRow = hasHeader ? 2 : 1;
    
            // place all the data into DataTable
            for (int rowNum = startRow; rowNum <= worksheet.Dimension.End.Row; rowNum++)
            {
                var wsRow = worksheet.Cells[rowNum, 1, rowNum, worksheet.Dimension.End.Column];
                DataRow row = dt.Rows.Add();
                foreach (var cell in wsRow)
                {
                    row[cell.Start.Column - 1] = cell.Text;
                }
            }
    
            return dt;
        }
    

    It will give you the correct column name in Datatable.

    User's image

    Hope this helps


    If it does, please accept the answer.

    Thanks

    Naimish Makwana

    1 person found this answer helpful.

  2. Cenk 1,036 Reputation points
    2023-01-18T17:36:58.28+00:00

    I think this works;

    public static DataTable ImportToDataTable(string filePath, string sheetName)
            {
                var dt = new DataTable();
                var fi = new FileInfo(filePath);
                // Check if the file exists
                if (!fi.Exists)
                    throw new Exception("File " + filePath + " Does Not Exists");
    
                // If you use EPPlus in a noncommercial context
                // according to the Polyform Noncommercial license:
                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                using var xlPackage = new ExcelPackage(fi);
                // get the first worksheet in the workbook
                var worksheet = xlPackage.Workbook.Worksheets[sheetName];
    
                dt = worksheet.Cells["A1:E37"].ToDataTable(c =>
                {
                    
                    c.FirstRowIsColumnNames = true;
                    c.Mappings.Add(3, "ReferenceNo", typeof(Guid), false, cellVal => new Guid(cellVal.ToString()));
                    
    
                });
    
               return dt;
            }
    
    0 comments No comments

  3. Cenk 1,036 Reputation points
    2023-01-18T17:46:27.5333333+00:00

    But I need to set Cells not manually, but how?

    dt = worksheet.Cells["A1:E37"].ToDataTable(c =>

    0 comments No comments

  4. Cenk 1,036 Reputation points
    2023-01-19T05:42:31.9+00:00

    This is what I need, hope helps someone else.

    public static DataTable ImportToDataTable(string filePath, string sheetName)
            {
                var dt = new DataTable();
                var fi = new FileInfo(filePath);
                // Check if the file exists
                if (!fi.Exists)
                    throw new Exception("File " + filePath + " Does Not Exists");
    
                // If you use EPPlus in a noncommercial context
                // according to the Polyform Noncommercial license:
                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                using var xlPackage = new ExcelPackage(fi);
                // get the first worksheet in the workbook
                var worksheet = xlPackage.Workbook.Worksheets[sheetName];
    
                dt = worksheet.Cells[1, 1, worksheet.Dimension.End.Row, worksheet.Dimension.End.Column].ToDataTable(c =>
                {
                    
                    c.FirstRowIsColumnNames = true;
                    // Ensure that the OrderDate column is casted to DateTime (in Excel it can sometimes be stored as a double/OADate)
                    c.Mappings.Add(3, "ReferenceNo", typeof(Guid), false, cellVal => new Guid(cellVal.ToString()));
                    
    
                });
    
                return dt;
            }
    
    0 comments No comments

  5. Jack J Jun 25,296 Reputation points
    2023-01-19T06:14:24.8566667+00:00

    @Cenk, Welcome to Microsoft Q&A, I am glad to hear that you problem has been solved, you could also set the data type for the GUID column individually.

    Like the following:

     foreach (var firstRowCell in worksheet.Cells[1, 1, 1, worksheet.Dimension.End.Column])
                {
                    dt.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
                }
                dt.Columns["ReferenceNo"].DataType = typeof(Guid);
    

    Based on my test, it also works well.

    Best Regards,

    Jack


    If the answer is the right solution, please click "Accept Answer" and upvote it.If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.