SqlBulkCopy ColumnMapping error CSV to DataTable to SQL Server Table

c# csv-import datatable sqlbulkcopy sql-server

Question

J'essaie d'insérer en bloc un fichier CSV dans une base de données SQL Server.

Le processus est .CSV fichier .CSV de DataTable à SqlBulkCopy à SQL Server.

Quand je lance ceci, j'obtiens cette erreur:

Le ColumnMapping donné ne correspond à aucune colonne de la source ou de la destination

Lorsque j'importe directement le fichier CSV dans SQL Server via Management Studio, cela fonctionne! Donc, je pense que le problème est ma conversion de table de données?

Voici mon code pour aller de .CSV à DataTable :

public DataTable CsvFileToDataTable(string filePath)
{
    var csvData = new DataTable("Table1");
    using (var csvReader = new TextFieldParser(filePath))
    {
        csvReader.SetDelimiters(new string[] { "," });
        csvReader.HasFieldsEnclosedInQuotes = true;
        var readFields = csvReader.ReadFields();

        foreach (var dataColumn in readFields.Select(column => new DataColumn(column) {AllowDBNull = true }))
        {
            csvData.Columns.Add(dataColumn);
        }
        while (!csvReader.EndOfData)
        {
            var data = csvReader.ReadFields();
            for (var i = 0; i < data.Length; i++)
            {
                if (data[i] == "")
                {
                    data[i] = null;
                }
            }
            csvData.Rows.Add(data);
        }
    }

    return csvData;
}

Et voici le code pour l'insertion de copie en bloc:

public void InsertData(DataTable table)
{
    using (var transactionScope = new TransactionScope())
    {
        using (var sqlConnection = new SqlConnection(this.ConnectionString))
        {
            sqlConnection.Open();

            using (var sqlBulkCopy = new SqlBulkCopy(sqlConnection))
            {
                sqlBulkCopy.DestinationTableName = table.TableName;

                foreach (var column in table.Columns)
                {
                    sqlBulkCopy.ColumnMappings.Add(column.ToString(), column.ToString());
                }

                sqlBulkCopy.WriteToServer(table);
            }

            transactionScope.Complete();
        }
    }
}

Est-ce que quelqu'un a des suggestions?

Merci

Réponse acceptée

Il se avère que si je tweked chaque méthode

foreach (var dataColumn in readFields.Select(column => new DataColumn(columntypeof(string)) { AllowDBNull = true, DefaultValue = string.Empty }))
{
    csvData.Columns.Add(dataColumn);
}

et dans la deuxième méthode, j'ai changé pour utiliser un index plutôt qu'un nom de colonne

for (var count = 0; count < table.Columns.Count; count++)
{
    sqlBulkCopy.ColumnMappings.Add(count, count);
}

Réponse populaire

J'ai pu utiliser ces exemples de code pour créer une solution efficace qui lit un csv, vérifie s'il existe des données, et si elles sont nettoyées et importent toutes les données csv dans la table:

private static void ProcessFile(string FilePath, string TableName)
{
    var dt = GetDataTable(FilePath, TableName);
    if (dt == null)
    {
        return;
    }
    if (dt.Rows.Count == 0)
    {
        AuditLog.AddInfo("No rows imported after reading file " + FilePath);
        return;
    }
    ClearData(TableName);
    InsertData(dt);
}
private static DataTable GetDataTable(string FilePath, string TableName)
{
    var dt = new DataTable(TableName);
    using (var csvReader = new TextFieldParser(FilePath))
    {
        csvReader.SetDelimiters(new string[] { "," });
        csvReader.HasFieldsEnclosedInQuotes = true;
        var readFields = csvReader.ReadFields();
        if (readFields == null)
        {
            AuditLog.AddInfo("Could not read header fields for file " + FilePath);
            return null;
        }
        foreach (var dataColumn in readFields.Select(column => new DataColumn(column, typeof(string)) { AllowDBNull = true, DefaultValue = string.Empty }))
        {
            dt.Columns.Add(dataColumn);
        }
        while (!csvReader.EndOfData)
        {
            var data = csvReader.ReadFields();
            if (data == null)
            {
                AuditLog.AddInfo(string.Format("Could not read fields on line {0} for file {1}", csvReader.LineNumber, FilePath));
                continue;
            }
            var dr = dt.NewRow();
            for (var i = 0; i < data.Length; i++)
            {
                if (!string.IsNullOrEmpty(data[i]))
                {
                    dr[i] = data[i];
                }
            }
            dt.Rows.Add(dr);
        }
    }
    return dt;
}
private static void ClearData(string TableName)
{
    SqlHelper.ExecuteNonQuery(ConfigurationUtil.ConnectionString, CommandType.Text, "TRUNCATE TABLE " + TableName);
}
private static void InsertData(DataTable table)
{
    using (var sqlBulkCopy = new SqlBulkCopy(ConfigurationUtil.ConnectionString))
    {
        sqlBulkCopy.DestinationTableName = table.TableName;
        for (var count = 0; count < table.Columns.Count; count++)
        {
            sqlBulkCopy.ColumnMappings.Add(count, count);
        }
        sqlBulkCopy.WriteToServer(table);
    }
}


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi