it-swarm.com.de

Laden Sie die CSV-Datei auf den SQL-Server hoch

Was ist der beste Weg, um eine große csv-Datendatei mit C # in den SQL-Server zu laden? Die Datei enthält etwa 30.000 Zeilen und 25 Spalten. 

22
user3083221

Zunächst einmal, Sie brauchen kein Programmierzeug. Sie können CSV-Dateien mit SQL-Verwaltungstools direkt in die SQL-Datenbank hochladen. Wenn Sie es jedoch wirklich durch Programmierung tun müssen, lesen Sie unten.

Ich persönlich denke, dass dieser Ansatz der effizienteste und einfachste Weg ist, durch Programmierung zu erreichen.

Im Allgemeinen können Sie es in zwei Schritten erreichen

1st ist das Lesen der CSV-Datei und das Speichern der Datensätze als DataTable.
2nd ist das Speichern der abgerufenen DataTable in der SQL-Datenbanktabelle als Masseneintrag

Dies ist eine Funktion, die CSV-Dateidaten als DataTable zurückgibt. Rufen Sie an und behalten Sie es in Erinnerung und Sie können damit machen, was Sie wollen.

Diese Funktion gibt die CSV-Lesedatei in DataTable zurück. 

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 - Verwenden Sie diese Funktion, um die abgerufene Datentabelle in die SQL-Tabelle einzufügen.

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);
         }
     }

Quelle

43
Kirk

Es gibt eine andere Möglichkeit, CSV per Programmierung in die Datenbank zu laden. Cinchoo ETL , eine Open Source-Bibliothek kann die Aufgabe übernehmen, CSV-Dateien mithilfe von DataReader in die Datenbank zu laden. Dabei handelt es sich um einen Streaming-Ansatz mit wenig bis gar keinem Speicheraufwand. 

Hier ist ein Beispiel, wie es geht

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

Der beste Weg, große CSV-Dateien in SQL Server zu importieren, ist die Verwendung von SqlBulkCopy zusammen mit der Implementierung von IDataReader. Das Gute daran ist, dass Sie nicht die gesamte Datei in den Arbeitsspeicher lesen (was beim DataTable-Ansatz der Fall ist) und Sie können die Größe des Stapels steuern, der an SQL Server gesendet wird. Das Schlechte daran ist, dass Sie IDataReader implementieren müssen, eine der längsten MS-Schnittstellen, die ich je gesehen habe.

Ich habe ein Nuget-Paket geschrieben, das den Trick für Sie erledigt. Es verwendet das awesome CsvHelper - Paket, so dass sehr wenige Konfigurationsschritte erforderlich sind. Das einfachste Szenario würde folgendermaßen aussehen:

//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);

Es gibt auch zusätzliche Konfigurationsoptionen für komplexere Szenarien (flexible Spaltenzuordnung, zusätzliche statische Spaltenwerte, die nicht in der CSV-Datei enthalten sind, Werttransformation.) Wenn Sie daran interessiert sind, ist das Projekt auf Github und als nuget-Paket verfügbar .

Als Referenz verwenden Sie SqlBulkCopy mit 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

Das klingt nach einem perfekten Job für SSIS. Es ist ein kostenloser Teil von SQL Server, kann alle CSV-Dateien in einem Ordner durchlaufen, ist sehr schnell und verfügt über eine hervorragende Fehlerbehandlung und Protokollierung.

1

Diese Technik verwendet die SQLBulkCopy () - Funktion, liest jedoch nicht die gesamte Datei in den Arbeitsspeicher.

Der Trick besteht darin, dass eine IDataReader-Klasse zum Lesen der CSV-Datei implementiert wird.

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

1
Michael Potter

Verwenden Sie System.Data.SqlClient.SqlBulkCopy class, um Daten in SQL-Tabellen einzufügen. Um diese Klasse verwenden zu können, müssen Sie auch CVS-Daten in DataTable konvertieren. Siehe hier eine der Möglichkeiten.

1
pakeha_by

Sie können auch Bulk Insert verwenden.

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

Seien Sie hier jedoch vorsichtig, da Tabellenname und CSV-Name identisch sein müssen und die Spaltenanzahl in der CSV mit der in der vordefinierten Tabelle übereinstimmen muss.

0
ruedi
    private void GetDataTabletFromCSVFile(string fileName)
    {
        DataTable dt = new DataTable();
        //dt.TableName = fileName;

        try
        {
            using (TextFieldParser csvReader = new TextFieldParser(fileName))
            {
                csvReader.SetDelimiters(new string[] { "," });
                csvReader.HasFieldsEnclosedInQuotes = true;
                string[] colFields = csvReader.ReadFields();
                //foreach (string column in colFields)
                //{
                //    DataColumn datecolumn = new DataColumn(column);
                //    datecolumn.AllowDBNull = true;
                //    dt.Columns.Add(datecolumn);
                //}
                dt.Columns.AddRange(new DataColumn[8] {
                    new DataColumn("Symbol", typeof(string)),
                new DataColumn("ISIN", typeof(string)),
                new DataColumn("Company", typeof(string)),
                new DataColumn("FirstListingDate", typeof(string)),
                new DataColumn("FaceValue", typeof(string)),
                new DataColumn("PaidUpValue", typeof(string)),
                new DataColumn("MarketLot",typeof(string)),
                new DataColumn("industry",typeof(string))
                });
                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;
                        }
                    }
                    dt.Rows.Add(fieldData);
                }
                var builder = new ConfigurationBuilder()
                    .SetBasePath(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location))
                    .AddJsonFile("appsettings.json");

                var configuration = builder.Build();
                string DBconnection = configuration.GetSection("ConnectionString").Value;
                using (SqlConnection dbConnection = new SqlConnection(DBconnection))
                {
                    dbConnection.Open();
                    using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
                    {
                        s.DestinationTableName = "Static.dbo.Securitiesinfo";
                        foreach (var column in dt.Columns)
                            s.ColumnMappings.Add(column.ToString(), column.ToString());
                        s.WriteToServer(dt);
                    }
                }

            }
        }
        catch (Exception ex)
        {
            var x = ex;
        }

    }
0
vijay