2016-04-15 13 views
0

因此,我有一個包含27列的網站位置信息數據庫。我編寫了一個批量導入功能,它可以接收一個CSV文件並允許您修改信息。當CSV文件包含每一列中的信息時,一切正常,但當空字符串/ null時,它會將空字符串推送到數據庫並清除之前的內容。C# - 導入一個空的字符串不會通過批量導入發送到數據庫的CSV

爲了能夠快速更新數據庫中的某些屬性,我的客戶端只需要放置站點的主鍵(我已經編碼了導入以便更新)並填寫了其他任何屬性必須填寫其餘的。因此,例如,對於一個位置的CSV文件可能是這個樣子:

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 

說這個網站已經存在於數據庫中,我只是想更新填充在字段留白的那些應該僅僅停留。一樣。

這是我到目前爲止的代碼

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

     } 

我的邏輯是,一旦信息從CSV導入文件就被移動到一個數據表,如果它包含空值,則在列數據表被刪除。所以沒有什麼可以映射到BulkUpdate列映射,因此沒有數據應該推送到該列的數據庫。

這不是因爲某些原因,我不知道爲什麼...有沒有更好的方法?

任何幫助,將不勝感激,謝謝。

+0

我只是建立單獨的更新語句並直接執行它們。 – Paparazzi

回答

1

有許多解決方案可以滿足您的需求。

我看到的一個問題是,如果用戶正在上傳具有多個行的項目,並且這些行具有不同的數據(比如一列在一行上空白,但在第二行填寫),那會導致它自行中斷該列將自己刪除。

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

在這種情況下,第1,3和4列(零基於此處)將被刪除,因爲它們具有空值,這會破壞您的預期目的。只有每行包含相同列中的數據時,寫入的邏輯纔會起作用。

我會建議將數據加載到一個臨時表中,並完成SQL中的任務,這將使您更好地控制數據加載過程。如果您有權訪問數據庫,請編寫一個存儲過程,然後將數據表的每一行傳入存儲過程,然後從那裏執行upsert操作。

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

上述代碼需要根據您的目的進行調整和修改。這只是一個例子。並且請注意,您的操作之間的連接無法關閉,或者臨時表將被刪除。您需要使用相同的連接執行插入和更新。

+0

你是對的我沒有想到其他網站的列將被刪除。那肯定會成爲一個問題。理想情況下,我希望使用帶有存儲過程的臨時表,但只需在此客戶端創建一個表,就需要整個同行評審過程,因此它可能不可行。謝謝。 – ouro

+0

@ouro,你不需要添加一個表 - 只需在代碼中創建一個臨時SQL表並使用它即可。我添加了一些代碼,希望能夠幫助您指導解決方案。儘管如此,你仍然需要做一些工作,因爲我沒有爲你整理所有東西。我以前從未真正使用這些批量操作,但希望這會有所幫助。 –

0

,如果你可以鏈接多個參數基礎構建了單獨的更新語句
您可以更新鏈接

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

但是這將是一個開放的SQL注入,所以你應該使用參數
我不知道更新在一個
如果不是,速度是一個問題,我會做一個更新異步,所以你正在執行當前正在創建下一個更新。