2016-04-15 3 views
0

So habe ich eine Datenbank mit Standortinformationen, die 27 Spalten enthält. Ich habe eine Bulk-Import-Funktion codiert, die eine CSV-Datei akzeptiert und Sie Informationen ändern können. Alles funktioniert gut, wenn die CSV-Datei Informationen in jeder Spalte enthält, aber wenn eine leere Zeichenfolge/null vorhanden ist, wird eine leere Zeichenfolge an die Datenbank gesendet und die zuvor vorhandene gelöscht.C# - Importieren einer CSV, wo leere Zeichenfolgen nicht durch Massenimport in die Datenbank gesendet werden

Um bestimmte Attribute in der Datenbank schnell aktualisieren zu können, möchte mein Klient nur den Primärschlüssel der Seite (den ich den Import kodieren möchte, um updatebar zu machen) und ein beliebiges anderes Attribut ohne eingeben den Rest ausfüllen müssen. So zum Beispiel eine CSV-Datei für einen Standort könnte wie folgt aussehen:

SITE32,,,,BS,11111,,43607,123566789,123456789,2.2.2.2,1.1.1.1.1,1.1.1.1,0,Test,Test,Testing,2,12123,5002,N/A,4,00201,3,000,3703,5 

Sagen Sie diese Seite bereits in der Datenbank vorhanden ist, ich möchte nur die Felder aktualisieren, die ausgefüllt sind diejenigen leer bleiben sollten einfach bleiben. das Gleiche.

Dies ist der Code, den ich

 protected void btnBulkSite_click(object sender, EventArgs e) 
      { 

       if (FileUpLoad1.HasFile) 
       { 
        FileUpLoad1.SaveAs(@"C:\temp\" + FileUpLoad1.FileName); 
        btnBulkSite.Text = "File Uploaded: " + FileUpLoad1.FileName; 
       } 
       else 
       { 
        btnBulkSite.Text = "No File Uploaded."; 
       } 
       DataTable tblcsv = new DataTable(); 

       tblcsv.Columns.Add("SERVER_ID", typeof(string)); 
       tblcsv.Columns.Add("SITE_NAME", typeof(string)); 
       tblcsv.Columns.Add("SITE_ADDRESS", typeof(string)); 
       tblcsv.Columns.Add("SITE_CITY", typeof(string)); 
       tblcsv.Columns.Add("SITE_STATE", typeof(string)); 
       tblcsv.Columns.Add("SITE_ZIPCODE", typeof(string)); 
       tblcsv.Columns.Add("SITE_COUNTY", typeof(string)); 
       tblcsv.Columns.Add("SITE_INTERNALZIP", typeof(string)); 
       tblcsv.Columns.Add("SITE_PHONE_NUM", typeof(string)); 
       tblcsv.Columns.Add("SITE_FAX_NUM", typeof(string)); 
       tblcsv.Columns.Add("SERVER_SUBNET_ADDR", typeof(string)); 
       tblcsv.Columns.Add("SERVER_IP_ADDR", typeof(string)); 
       tblcsv.Columns.Add("SERVER_GATEWAY_ADDR", typeof(string)); 
       tblcsv.Columns.Add("COSTCENTER_NUM"); 
       tblcsv.Columns.Add("DCMF_NAME", typeof(string)); 
       tblcsv.Columns.Add("LU_ID", typeof(string)); 
       tblcsv.Columns.Add("XIDPU_ID", typeof(string)); 
       tblcsv.Columns.Add("TRAININGSITE_IND"); 
       tblcsv.Columns.Add("PBA_FICS_NUM"); 
       tblcsv.Columns.Add("PBA_CITY_ID", typeof(string)); 
       tblcsv.Columns.Add("REGION_NAME", typeof(string)); 
       tblcsv.Columns.Add("SITETYPE_ID"); 
       tblcsv.Columns.Add("PBA_OFFICE_ID", typeof(string)); 
       tblcsv.Columns.Add("SITEORIGIN_ID"); 
       tblcsv.Columns.Add("REGION_ID", typeof(string)); 
       tblcsv.Columns.Add("PBA_BANK_ID", typeof(string)); 
       tblcsv.Columns.Add("SITE_REGION_ID"); 



       System.IO.StreamReader stream = new System.IO.StreamReader(FileUpLoad1.PostedFile.InputStream); 

       string ReadCSV = stream.ReadToEnd(); 
       foreach (string csvRow in ReadCSV.Split('\n')) 
        { 

         if (!string.IsNullOrEmpty(csvRow)) 
         { 
         tblcsv.Rows.Add(); 
         int count = 0; 

         foreach (string FileRec in csvRow.Split(',')) 
         { 
          tblcsv.Rows[tblcsv.Rows.Count - 1][count] = FileRec; 

          count++; 
         } 
        } 
       } 

       RemoveAllNullColumnsFromDataTable(tblcsv); 

      } 

    public void RemoveAllNullColumnsFromDataTable(DataTable tblcsv) 
     { 
      for (int h = 0; h < tblcsv.Rows.Count; h++) 
      { 
       if (tblcsv.Rows[h].IsNull(0) == true) 
       { 
        tblcsv.Rows[h].Delete(); 
       } 

      } 
      tblcsv.AcceptChanges(); 
      foreach (var column in tblcsv.Columns.Cast<DataColumn>().ToArray()) 
      { 
       if (tblcsv.AsEnumerable().All(dr => dr.IsNull(column))) 
        tblcsv.Columns.Remove(column); 
      } 
      tblcsv.AcceptChanges(); 
      InsertCSVRecords(tblcsv); 
     } 

     public void InsertCSVRecords(DataTable csvdt) 
     { 
      connection(); 

      //SqlBulkCopy objbulk = new SqlBulkCopy(con); 
      var objbulk = new BulkOperation(con); 
      objbulk.AllowUpdatePrimaryKeys = true; 
      objbulk.DestinationTableName = "SITE_INFO"; 


      objbulk.ColumnMappings.Add("SERVER_ID", "SERVER_ID", true); 
      objbulk.ColumnMappings.Add("SITE_NAME", "SITE_NAME"); 
      objbulk.ColumnMappings.Add("SITE_ADDRESS", "SITE_ADDRESS"); 
      objbulk.ColumnMappings.Add("SITE_CITY", "SITE_CITY"); 
      objbulk.ColumnMappings.Add("SITE_STATE", "SITE_STATE"); 
      objbulk.ColumnMappings.Add("SITE_ZIPCODE", "SITE_ZIPCODE"); 
      objbulk.ColumnMappings.Add("SITE_COUNTY", "SITE_COUNTY"); 
      objbulk.ColumnMappings.Add("SITE_INTERNALZIP", "SITE_INTERNALZIP"); 
      objbulk.ColumnMappings.Add("SITE_PHONE_NUM", "SITE_PHONE_NUM"); 
      objbulk.ColumnMappings.Add("SITE_FAX_NUM", "SITE_FAX_NUM"); 
      objbulk.ColumnMappings.Add("SERVER_SUBNET_ADDR", "SERVER_SUBNET_ADDR"); 
      objbulk.ColumnMappings.Add("SERVER_IP_ADDR", "SERVER_IP_ADDR"); 
      objbulk.ColumnMappings.Add("SERVER_GATEWAY_ADDR", "SERVER_GATEWAY_ADDR"); 
      objbulk.ColumnMappings.Add("COSTCENTER_NUM", "COSTCENTER_NUM"); 
      objbulk.ColumnMappings.Add("DCMF_NAME", "DCMF_NAME"); 
      objbulk.ColumnMappings.Add("LU_ID", "LU_ID"); 
      objbulk.ColumnMappings.Add("XIDPU_ID", "XIDPU_ID"); 
      objbulk.ColumnMappings.Add("TRAININGSITE_IND", "TRAININGSITE_IND"); 
      objbulk.ColumnMappings.Add("PBA_FICS_NUM", "PBA_FICS_NUM"); 
      objbulk.ColumnMappings.Add("PBA_CITY_ID", "PBA_CITY_ID"); 
      objbulk.ColumnMappings.Add("REGION_NAME", "REGION_NAME"); 
      objbulk.ColumnMappings.Add("SITETYPE_ID", "SITETYPE_ID"); 
      objbulk.ColumnMappings.Add("PBA_OFFICE_ID", "PBA_OFFICE_ID"); 
      objbulk.ColumnMappings.Add("SITEORIGIN_ID", "SITEORIGIN_ID"); 
      objbulk.ColumnMappings.Add("REGION_ID", "REGION_ID"); 
      objbulk.ColumnMappings.Add("PBA_BANK_ID", "PBA_BANK_ID"); 
      objbulk.ColumnMappings.Add("SITE_REGION_ID", "SITE_REGION_ID"); 



      con.Open(); 
      objbulk.BulkUpdate(csvdt); 

      con.Close(); 

     } 

Meine Logik so weit ist, dass, sobald die Informationen aus der CSV importiert Datei, die es zu einem Datentabelle bewegt wird, und wenn es einen Nullwert enthält dann die Spalte in Die Datentabelle wurde entfernt. Daher müssen den BulkUpdate-Spaltenzuordnungen und den Daten, die für diese Spalte an die Datenbank übertragen werden sollen, keine Daten zugeordnet werden.

Dies funktioniert jedoch aus irgendeinem Grund nicht und ich weiß nicht warum ... gibt es einen besseren Weg?

Jede Hilfe wäre dankbar, danke.

+0

Ich würde nur einzelne Update-Anweisungen aufbauen und sie direkt ausführen. – Paparazzi

Antwort

1

Es gibt eine Vielzahl von Lösungen, um dorthin zu gelangen, wo Sie brauchen.

Ein Problem, das ich sehe, ist, dass, wenn die Person Elemente mit mehreren Zeilen hochlädt und diese Zeilen unterschiedliche Daten haben (sagen wir, eine Spalte ist leer in einer Zeile, aber in einer zweiten Zeile ausgefüllt), wird es seitdem brechen Die Spalte hat sich selbst gelöscht.

SITE32,,1,2,,... 
SITE32,1,2,,,... 

In diesem Fall Spalten 1, 3 und 4 (Null stützen hier) würde, da sie Nullwerte haben werden gelöscht, die beabsichtigten Zweck vereiteln würden. Ihre geschriebene Logik funktioniert nur, wenn jede Zeile Daten in denselben Spalten enthält.

Ich würde empfehlen, die Daten in eine temporäre Tabelle zu laden und die Aufgabe in SQL zu beenden, die Ihnen mehr Kontrolle über den Datenladeprozess geben würde. Wenn Sie Zugriff auf die Datenbank haben, schreiben Sie eine gespeicherte Prozedur, übergeben Sie dann jede Zeile der Datentabelle an die gespeicherte Prozedur, und führen Sie von dort aus die Upsert-Operation aus.

SqlCommand cmd = new SqlCommand("",conn()); 
cmd.CommandText = "CREATE TABLE #tmp (
[SERVER_ID] NVARCHAR(MAX), 
[SITE_NAME] NVARCHAR(MAX), 
[SITE_ADDRESS] NVARCHAR(MAX), 
[SITE_CITY] NVARCHAR(MAX), 
[SITE_STATE] NVARCHAR(MAX), 
[SITE_ZIPCODE] NVARCHAR(MAX), 
[SITE_COUNTY] NVARCHAR(MAX), 
[SITE_INTERNALZIP] NVARCHAR(MAX), 
[SITE_PHONE_NUM] NVARCHAR(MAX), 
[SITE_FAX_NUM] NVARCHAR(MAX), 
[SERVER_SUBNET_ADDR] NVARCHAR(MAX), 
[SERVER_IP_ADDR] NVARCHAR(MAX), 
[SERVER_GATEWAY_ADDR] NVARCHAR(MAX), 
[COSTCENTER_NUM] NVARCHAR(MAX), 
[DCMF_NAME] NVARCHAR(MAX), 
[LU_ID] NVARCHAR(MAX), 
[XIDPU_ID] NVARCHAR(MAX), 
[TRAININGSITE_IND] NVARCHAR(MAX), 
[PBA_FICS_NUM] NVARCHAR(MAX), 
[PBA_CITY_ID] NVARCHAR(MAX), 
[REGION_NAME] NVARCHAR(MAX), 
[SITETYPE_ID] NVARCHAR(MAX), 
[PBA_OFFICE_ID] NVARCHAR(MAX), 
[SITEORIGIN_ID] NVARCHAR(MAX), 
[REGION_ID] NVARCHAR(MAX), 
[PBA_BANK_ID] NVARCHAR(MAX), 
[SITE_REGION_ID] NVARCHAR(MAX) 
); 
conn.Open(); 
cmd.ExecuteNonQuery(); 

SqlBulkCopy bc = new SqlBulkCopy(); 
bc.DestinationTableName = "#tmp"; 
bc.BulkCopyTimeout = 600; 
bc.WriteToServer(dt); 
bc.Close(); 

cmd.CommandText = "UPDATE t SET t.SERVER_ID = CASE WHEN tmp.SERVER_ID <> '' THEN tmp.SERVER_ID ELSE t.SERVER_ID END, ..... t.SITE_REGION_ID = CASE WHEN tmp.SITE_REGION_ID <> '' THEN tmp.SERVER_ID ELSE t.SERVER_ID END FROM Table t INNER JOIN #tmp AS tmp ON t.SERVER_ID = tmp.SERVER_ID"; 
cmd.ExecuteNonQuery(); 
conn.Close(); 

Der obige Code muss für Ihre Zwecke angepasst und überarbeitet werden. Dies ist nur ein Beispiel.Beachten Sie, dass die Verbindung zwischen Ihren Vorgängen nicht geschlossen werden kann oder dass die temporäre Tabelle gelöscht wird. Sie müssen sowohl das Einfügen als auch das Aktualisieren mit derselben Verbindung durchführen.

+0

Sie haben Recht Ich habe nicht daran gedacht, dass die Spalten für die anderen Seiten gelöscht werden. Das wäre definitiv ein Problem. Ich würde idealerweise eine temporäre Tabelle mit einer gespeicherten Prozedur verwenden wollen, aber das Erstellen einer Tabelle auf diesem Client erfordert einen gesamten Peer-Review-Prozess, so dass es wahrscheinlich nicht ausführbar wäre. trotzdem danke. – ouro

+0

@ouro, Sie müssen keine Tabelle hinzufügen - erstellen Sie einfach eine temporäre SQL-Tabelle im Code und verwenden Sie diese. Ich habe Code hinzugefügt, der Ihnen hoffentlich zu einer Lösung verhelfen wird. Sie müssen trotzdem etwas arbeiten, um es zu bekommen, da ich das Ganze nicht für Sie eingegeben habe. Und ich habe diese Bulk-Operationen noch nie wirklich benutzt, aber hoffentlich wird das helfen. –

0

Aufbau individuelle Update-Anweisung
können Sie Kette Updates

update [test].[dbo].[Table_1] set value1 = 'newOne' where iden = 1; 
    update [test].[dbo].[Table_1] set value1 = 'newTwo' where iden = 2; 

Aber das wäre ein offen für SQL-Injection, so dass Sie Parameter
Ich bin nicht sicher, verwenden sollten, wenn Sie Kette können mehrere Parameter basierend Updates in einem
Wenn nicht und Geschwindigkeit ein Problem ist, würde ich ein Update asynch tun, so dass Sie das nächste Update erstellen, während die aktuelle ausgeführt wird.

Verwandte Themen