简体   繁体   中英

OpenXML and c# error to insert datatable in sql server

I have a C# application which serves to recover data from .XLSX file and insert the data to SQL server table.

For example I have a datatable with Identity and 3 columns. When i execute SQL command. I have this error:

INSERT into an identity column not allowed on table variables. The data for table-valued parameter "@product" doesn't conform to the table type of the parameter. SQL Server error is: 200, state: 7

Stored Procedure

ALTER PROCEDURE [dbo].[InserimentoDatiExcel](@product [udtInserimentoDatiExcel] readonly)

AS
BEGIN
    INSERT INTO Prova
    (ID, PIPPO, PLUTO, PAPERINO)
    SELECT *
    FROM @product
    --FROM Prova
    --WHERE ID IN (SELECT ID FROM @product)

END

Table

CREATE TYPE [dbo].[udtInserimentoDatiExcel] AS TABLE(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [PIPPO] [varchar](1) NOT NULL,
    [PLUTO] [varchar](1) NOT NULL,
    [PAPERINO] [varchar](1) NOT NULL,
    PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = ON)
)
GO

Datatable : Image

Code

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace BatchReadExcel
{
    class Program
    {
        static void Main()
        {
            try
            {
                DataTable dt = new DataTable();
                using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(@"C:\Users\f.piano\Documents\prova.xlsx", false))
                {
                    WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
                    IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
                    string relationshipId = sheets.First().Id.Value;
                    WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
                    Worksheet workSheet = worksheetPart.Worksheet;
                    SheetData sheetData = workSheet.GetFirstChild<SheetData>();
                    IEnumerable<Row> rows = sheetData.Descendants<Row>();
                    //TEST
                    //dt.Columns.Add("ID", typeof(Int32));
                    dt.Columns.Add("ID", typeof(Guid));
                    dt.Columns["ID"].AutoIncrement = true;
                    dt.Columns["ID"].AutoIncrementSeed = 0;
                    dt.Columns["ID"].AutoIncrementStep = 1;
                    //TEST
                    foreach (Cell cell in rows.ElementAt(0))
                    {
                        dt.Columns.Add(GetCellValue(spreadSheetDocument, cell));
                    }
                    foreach (Row row in rows) //this will also include your header row...
                    {
                        DataRow tempRow = dt.NewRow();
                        /*Si inserisce columnIndex = 1 quando devi utilizzare
                          l'autoincrement sulla prima colonna (in questo caso ID)*/
                        int columnIndex = 1;
                        foreach (Cell cell in row.Descendants<Cell>())
                        {
                            // Gets the column index of the cell with data
                            int cellColumnIndex = (int)GetColumnIndexFromName(GetColumnName(cell.CellReference));
                            //cellColumnIndex--; //zero based index
                            if (columnIndex < cellColumnIndex)
                            {
                                do
                                {
                                    tempRow[columnIndex] = 1;
                                    columnIndex++;
                                }
                                while (columnIndex < cellColumnIndex);
                            }

                            tempRow[columnIndex] = GetCellValue(spreadSheetDocument, cell);

                            columnIndex++;
                        }
                        dt.Rows.Add(tempRow);
                    }
                }
                dt.Rows.RemoveAt(0); //rimuove la prima riga in cui ci sono le colonne

                //leggo le righe di una colonna specifica
                //string pippoRows = "";
                //for (int i = 0; i < dt.Rows.Count; i++)
                //{
                //    //pippoRows = Convert.ToInt32(dt.Rows[i]["PIPPO"]);
                //    pippoRows = Convert.ToString(dt.Rows[i]["PIPPO"]);
                //    //Similarly for QuantityInIssueUnit_uom.
                //}

                //TODO: Insert data in SQL Server
                var stringaConnessione = Properties.Settings.Default.connectionString;
                SqlConnection sqlcon = new SqlConnection();
                sqlcon.ConnectionString = stringaConnessione;
                SqlCommand sqlcmd = new SqlCommand("InserimentoDatiExcel", sqlcon);
                sqlcmd.CommandType = CommandType.StoredProcedure;

                //sqlcmd.Parameters.AddWithValue("@pippo", dt.Columns["PIPPO"].Container);
                sqlcmd.Parameters.AddWithValue("@product", dt);
                //sqlcmd.Parameters.Add(new SqlParameter("@pippo", dt.Columns["PIPPO"].ColumnMapping));
                sqlcon.Open();
                sqlcmd.ExecuteNonQuery();
                sqlcon.Close();

            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// Given a cell name, parses the specified cell to get the column name.
        /// </summary>
        /// <param name="cellReference">Address of the cell (ie. B2)</param>
        /// <returns>Column Name (ie. B)</returns>
        public static string GetColumnName(string cellReference)
        {
            // Create a regular expression to match the column name portion of the cell name.
            Regex regex = new Regex("[A-Za-z]+");
            Match match = regex.Match(cellReference);
            return match.Value;
        }
        /// <summary>
        /// Given just the column name (no row index), it will return the zero based column index.
        /// Note: This method will only handle columns with a length of up to two (ie. A to Z and AA to ZZ). 
        /// A length of three can be implemented when needed.
        /// </summary>
        /// <param name="columnName">Column Name (ie. A or AB)</param>
        /// <returns>Zero based index if the conversion was successful; otherwise null</returns>
        public static int? GetColumnIndexFromName(string columnName)
        {

            //return columnIndex;
            string name = columnName;
            int number = 0;
            int pow = 1;
            for (int i = name.Length - 1; i >= 0; i--)
            {
                number += (name[i] - 'A' + 1) * pow;
                pow *= 26;
            }
            return number;
        }
        public static string GetCellValue(SpreadsheetDocument document, Cell cell)
        {
            SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
            if (cell.CellValue == null)
            {
                return "";
            }
            string value = cell.CellValue.InnerXml;
            if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
            {
                return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
            }
            else
            {
                return value;
            }
        }
    }
}

In your first code snippet you're inserting the ID column which is an identity column (cannot be inserted).

You need to update your code to NOT include the ID column.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM