2015-04-03 54 views
0

我有一個查詢通過SqlDataReader獲取報告數據,並將SqlDataReader發送到將內容導出到.CSV文件的方法;但是,列名顯示在.CSV文件中,它們出現在數據庫中的方式並不理想。SqlDataReader在導出到csv時更改列名稱

我不想更改查詢本身(更改名稱以具有空格),因爲此查詢在其映射到對象且空間不起作用的另一個位置中調用。我不想創建重複的查詢,因爲維護可能有問題。我也不想修改寫出.CSV的方法,因爲這是一種全局使用的方法。

我可以在填充數據閱讀器之後但在將其發送到.CSV方法之前修改列名稱?如果是這樣,怎麼樣?

如果我不能這樣做,我可以這樣做,如果它是DataTable而不是?

這裏的一般流程:

public static SqlDataReader RunMasterCSV(Search search) 
    { 
     SqlDataReader reader = null; 

     using (Network network = new Network()) 
     { 
      using (SqlCommand cmd = new SqlCommand("dbo.MasterReport")) 
      { 
       cmd.CommandType = CommandType.StoredProcedure; 
       //Parameters here... 

       network.FillSqlReader(cmd, ref reader); 

       <-- Ideally would like to find a solution here --> 
       return reader; 
      } 
     } 
    } 

    public FileInfo CSVFileWriter(SqlDataReader reader) 
    { 
     DeleteOldFolders(); 

     FileInfo file = null; 

     if (reader != null) 
     { 
      using (reader) 
      { 
       var WriteDirectory = GetExcelOutputDirectory(); 
       double folderToSaveInto = Math.Ceiling((double)DateTime.Now.Hour/Folder_Age_Limit.TotalHours); 
       string uploadFolder = GetExcelOutputDirectory() + "\\" + DateTime.Now.ToString("ddMMyyyy") + "_" + folderToSaveInto.ToString(); 

       //Add directory for today if one does not exist 
       if (!Directory.Exists(uploadFolder)) 
        Directory.CreateDirectory(uploadFolder); 

       //Generate random GUID fileName 
       file = new FileInfo(uploadFolder + "\\" + Guid.NewGuid().ToString() + ".csv"); 
       if (file.Exists) 
        file.Delete(); 

       using (file.Create()) { /*kill the file stream immediately*/}; 
        StringBuilder sb = new StringBuilder(); 

        if (reader.Read()) 
        { 
         //write the column names 
         for (int i = 0; i < reader.FieldCount; i++) 
         { 
          AppendValue(sb, reader.GetName(i), (i == reader.FieldCount - 1)); 
         } 

         //write the column names 
         for (int i = 0; i < reader.FieldCount; i++) 
         { 
          AppendValue(sb, reader[i] == DBNull.Value ? "" : reader[i].ToString(), (i == reader.FieldCount - 1)); 
         } 

         int rowcounter = 1; 

         while (reader.Read()) 
         { 
          for (int i = 0; i < reader.FieldCount; i++) 
          { 
           AppendValue(sb, reader[i] == DBNull.Value ? "" : reader[i].ToString(), (i == reader.FieldCount - 1)); 
          } 

          rowcounter++; 

          if (rowcounter == MaxRowChunk) 
          { 
           using (var sw = file.AppendText()) 
           { 
            sw.Write(sb.ToString()); 
            sw.Close(); 
            sw.Dispose(); 
           } 

           sb = new StringBuilder(); 
           rowcounter = 0; 
          } 
         } 

         if (sb.Length > 0) 
         { 
          //write the last bit 
          using (var sw = file.AppendText()) 
          { 
           sw.Write(sb.ToString()); 
           sw.Close(); 
           sw.Dispose(); 

           sb = new StringBuilder(); 
          } 
         } 
        } 
       } 
     } 

     return file; 
    } 
+1

沒有看到你如何實際使用讀卡器來寫,很難給你一個確切的答覆文件,但爲什麼不乾脆改列名,當你將其導出爲CSV文件? – Tim 2015-04-03 20:04:08

+0

但是,如前所述,我已經包含了編寫CSV的代碼,但我不想爲此報告定製此方法,因爲它是全局使用的方法。謝謝 – 2015-04-03 20:19:41

+0

您使用的是哪個版本的Sql Server? – 2015-04-03 20:33:27

回答

1

我會嘗試你的CSVFileWriter的重構。

首先,你應該添加一個委託聲明

public delegate string onColumnRename(string); 

然後創造一個你與讀者一起通過委託

public FileInfo CSVFileWriter(SqlDataReader reader, onColumnRename renamer) 
{ 
    // Move here all the code of the old CSVFileWriter 
    ..... 
} 

移動以前CSVFileWriter的代碼添加到您的CSVFileWriter過載新方法,從舊的一個叫新的一個

public FileInfo CSVFileWriter(SqlDataReader reader) 
{ 
    // Pass null for the delegate to the new version of CSVFileWriter.... 
    return this.CSVFileWriter(reader, null) 
} 

這會使舊方法的現有客戶感到高興。對他們來說,一切都沒有改變.....

內CSVFileWriter的新版本,你改變準備列名的代碼

for (int i = 0; i < reader.FieldCount; i++) 
{ 
    string colName = (renamer != null ? renamer(reader.GetName(i)) 
             : reader.GetName(i)) 
    AppendValue(sb, colName, (i == reader.FieldCount - 1)); 
} 

現在是剛剛創建的轉換功能更名的事你列名

private string myColumnRenamer(string columnName) 
{ 
    if(columnName == "yourNameWithoutSpaces") 
     return "your Name with Spaces"; 
    else 
     return text; 
} 

這可以通過一個靜態字典中的最佳去除IFS的列表

此時你可以打電話給新CSVFileWriter傳遞你的函數

FileInfo fi = CSVFileWrite(reader, myColumnRenamer); 
+0

你提到使用靜態字典,而不是if,switch語句也是一個不錯的選擇,或者是靜態字典最好的選擇性能明智嗎? – 2015-04-06 12:21:45

+0

我寧願靜態字典只是簡單的代碼,將需要執行映射,但正如你可以[從這個答案閱讀](http://stackoverflow.com/questions/11617091/in-a-switch- vs-dictionary-for-a-value-of-func-which-is-faster-and-why)字典對於演出可能也更好 – Steve 2015-04-06 13:08:53

+1

感謝您的所有努力:) – 2015-04-06 13:39:31