SQL Bulk Insert Problem while inserting excel data

Cenk 956 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;
        }
    }
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
697 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,386 questions
SQL Server
SQL Server
A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.
12,699 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,237 questions
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Naimish Makwana 170 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 956 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 956 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 956 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 24,286 Reputation points Microsoft Vendor
    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.