web-dev-qa-db-fra.com

Télécharger un fichier CSV sur un serveur SQL

Quel est le meilleur moyen de télécharger un fichier de données csv volumineux sur SQL Server en utilisant C #? Le fichier contient environ 30 000 lignes et 25 colonnes. 

22
user3083221

D'abord, vous n'avez pas besoin de choses de programmation. Vous pouvez télécharger directement des fichiers CSV dans une base de données SQL avec des outils de gestion SQL. Cependant, si vous avez vraiment besoin de le faire par le biais de la programmation, veuillez lire ci-dessous.

Personnellement, je pense que cette approche est la manière la plus efficace et la plus simple de faire de la programmation.

_ {En général, vous pouvez y arriver en deux étapes} _

La 1re étape consiste à lire le fichier CSV et à conserver les enregistrements sous la forme DataTable.
2nd step stocke la DataTable récupérée dans la table de base de données SQL en tant qu'entrée en bloc

C’est une fonction qui renvoie les données de fichier CSV sous la forme DataTable. Appelez et gardez-le en mémoire et vous pourrez en faire ce que vous voudrez.

Cette fonction va renvoyer le fichier de lecture CSV dans DataTable. 

private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
    {
        DataTable csvData = new DataTable();
        try
        {
          using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
             {
                csvReader.SetDelimiters(new string[] { "," });
                csvReader.HasFieldsEnclosedInQuotes = true;
                string[] colFields = csvReader.ReadFields();
                foreach (string column in colFields)
                {
                    DataColumn datecolumn = new DataColumn(column);
                    datecolumn.AllowDBNull = true;
                    csvData.Columns.Add(datecolumn);
                }
                while (!csvReader.EndOfData)
                {
                    string[] fieldData = csvReader.ReadFields();
                    //Making empty value as null
                    for (int i = 0; i < fieldData.Length; i++)
                    {
                        if (fieldData[i] == "")
                        {
                            fieldData[i] = null;
                        }
                    }
                    csvData.Rows.Add(fieldData);
                }
            }
        }
        catch (Exception ex)
        {
           return null;
        }
        return csvData;
    }
  }

SQLBulkCopy - Utilisez cette fonction pour insérer le DataTable récupéré dans la table SQL

static void InsertDataIntoSQLServerUsingSQLBulkCopy(DataTable csvFileData)
{
    using(SqlConnection dbConnection = new SqlConnection("Data Source=ProductHost;Initial Catalog=yourDB;Integrated Security=SSPI;"))
    {
         dbConnection.Open();
         using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
         {
             s.DestinationTableName = "Your table name";
             foreach (var column in csvFileData.Columns)
             s.ColumnMappings.Add(column.ToString(), column.ToString());
             s.WriteToServer(csvFileData);
         }
     }

La source

43
Kirk

Voici un autre moyen de télécharger un fichier CSV dans une base de données via la programmation. Cinchoo ETL , une bibliothèque open source peut télécharger des fichiers CSV vers une base de données à l’aide de DataReader, une méthode de transmission en continu ne nécessitant que peu de mémoire. 

Voici un exemple comment le faire

string connectionstring = @"#YOUR DB ConnectionString#";
using (SqlBulkCopy bcp = new SqlBulkCopy(connectionstring))
{
    using (var p = new ChoCSVReader("#YOUR CSV FILE#").WithFirstLineHeader())
    {
        bcp.DestinationTableName = "#TABLENAME#";
        bcp.EnableStreaming = true;
        bcp.BatchSize = 10000;
        bcp.BulkCopyTimeout = 0;
        bcp.NotifyAfter = 100;
        bcp.SqlRowsCopied += delegate (object sender, SqlRowsCopiedEventArgs e)
        {
            Console.WriteLine(e.RowsCopied.ToString("#,##0") + " rows copied.");
        };
        bcp.WriteToServer(p.AsDataReader());
    }
}
3
RajN

Le meilleur moyen que j’ai trouvé d’importer des fichiers CSV volumineux dans SQL Server est d’utiliser SqlBulkCopy avec la mise en oeuvre IDataReader. L'avantage, c'est que vous ne lisez pas l'intégralité du fichier en mémoire (comme dans le cas de l'approche DataTable) et que vous pouvez contrôler la taille du lot envoyé à SQL Server. Le problème, c’est que vous devez implémenter IDataReader, qui est l’une des interfaces MS les plus longues que j’ai jamais vue.

J'ai écrit un paquet de pépites qui fait le tour pour vous. Il utilise le paquet génial CsvHelper donc il y a très peu de configuration requise. Le scénario le plus simple ressemblerait à ceci:

//Instantiate the reader, providing the list of columns which matches 1 to 1 the data table structure.
var dataReader = new CsvDataReader(filePath,
    new List<TypeCode>(5)
    {
        TypeCode.String,
        TypeCode.Decimal,
        TypeCode.String,
        TypeCode.Boolean,
        TypeCode.DateTime
    });

bulkCopyUtility.BulkCopy("TableName", dataReader);

Il existe également des options de configuration supplémentaires pour des scénarios plus complexes (mappage de colonne flexible, valeurs de colonne statiques supplémentaires qui ne figurent pas dans le fichier csv, transformation de valeur) . Si cela vous intéresse, le projet est sur Github et disponible sous forme de paquet nuget .

Pour référence, voici comment utiliser SqlBulkCopy avec IDataReader:

public void BulkCopy(string tableName, IDataReader dataReader, Action<SqlBulkCopy>  configureSqlBulkCopy)
{
    using (SqlConnection dbConnection = new SqlConnection(connectionString))
    {
        dbConnection.Open();

        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(dbConnection))
        {
            bulkCopy.BatchSize = 3000; //Data will be sent to SQL Server in batches of this size
            bulkCopy.EnableStreaming = true;
            bulkCopy.DestinationTableName = tableName;

            //This will ensure mapping based on names rather than column position
            foreach (DataColumn column in dataReader.GetSchemaTable().Columns)
            {
                bulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
            }

            //If additional, custom configuration is required, invoke the action
            configureSqlBulkCopy?.Invoke(bulkCopy);

            try
            {
                // Write from the source to the destination.
                bulkCopy.WriteToServer(dataReader);
            }
            finally
            {
                dataReader.Close();
            }
        }
    }
}
3
Michal Ciesielski

Cela semble être un travail parfait pour SSIS. C'est une partie gratuite de SQL Server, elle peut parcourir tous les fichiers csv d'un dossier, est très rapide et offre une excellente gestion et journalisation des erreurs.

1
benjamin moskovits

Cette technique utilise la fonctionnalité SQLBulkCopy (), mais ne lit pas l'intégralité du fichier en mémoire.

L'astuce consiste à implémenter une classe IDataReader pour lire le fichier .csv.

https://www.codeproject.com/Tips/1029831/Fast-and-Simple-IDataReader-Implementation-to-Read

1
Michael Potter

Utilisez System.Data.SqlClient.SqlBulkCopy class pour insérer des données dans des tables Sql. Pour utiliser cette classe, vous devez également convertir les données CVS en DataTable, voir ici l’un des moyens.

1
pakeha_by

Vous pouvez également utiliser Bulk Insert

Public Shared Function bulkQuery()

        Dim query As StringBuilder = New StringBuilder

        query.Append("USE Import_DB BULK INSERT dbo.[Insert_Table] FROM")
        query.Append(" 'C:\Insert_Table.csv' ")
        query.Append("With (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n')")

        Return query.ToString

    End Function

Soyez prudent ici car le nom de la table et le nom du fichier csv doivent être identiques, de même que le nombre de colonnes du fichier csv doit être identique à celui de la table prédéfinie.

0
ruedi