2015-06-17 50 views
0

雖然我很少使用LINQ,但LINQ並不好。如何通過LINQ直接從CSV文件中查詢和提取數據

我已經開發出明智的顯示輸出CSR和時間間隔明智數據 像下面

CSR Name   Time Interval  Incoming OutGoing Call Transfer Missed Call 
--------- ------------------ -------- -------- ------------- ------------ 
ACCTS  14:30:01--15:00:00 0 0  0  0 
ACCTS  15:00:01--15:30:00 0 0  1  0 
ACCTS  13:30:01--14:00:00 5 2  0  2 
ACCTS  14:00:01--14:30:00 1 0  0  0 
ACCTS  16:30:01--17:00:00 0 3  0  0 
ACCTS  17:00:01--17:30:00 4 0  1  2 
Christy  14:30:01--15:00:00 1 5  0  0 
Christy  15:00:01--15:30:00 2 7  1  0 
Christy  13:30:01--14:00:00 0 11  0  2 
SUZY  14:30:01--15:00:00 1 0  0  0 
SUZY  15:00:01--15:30:00 0 0  2  2 
SUZY  13:30:01--14:00:00 2 1  0  0 

我在這裏給我帶來上述輸出C#程序代碼。

private void FetchData(string tableName) 
     { 
      TimeSpan tsStart, tsEnd; 
      string strSql = ""; 
      srcTable = new DataTable(); 
      srcTable.TableName = "data"; 
      srcTable.Columns.Add("CSR Name"); 
      srcTable.Columns.Add("Time"); 
      srcTable.Columns.Add("Incoming Calls"); 
      srcTable.Columns.Add("Outgoing Calls"); 
      srcTable.Columns.Add("Calls Transfer"); 
      srcTable.Columns.Add("Missed Calls"); 
      DataRow dr = null; 
      int incall = 0, outcall = 0, transfercall = 0, totmisscall = 0; 
      bool flag = true; 
      string StartTime = "", EndTime = ""; 

      string DayOfWeek = DateTime.Parse(dtVal.Value.ToString()).ToString("ddd"); 
      string st_Time = string.Empty, end_Time = string.Empty; 

      st_Time="08:00:00"; 
      end_Time="17:30:00"; 

      // GetAllCSR function return datatable with all distinct CSR name excluding name start with VM and Voice Mail 
      DataTable dtCSRName = GetAllCSR(tableName,txtCSRName.Text); 
      string strCSRName = ""; 

      if (dtCSRName != null) 
      { 
       foreach (DataRow row in dtCSRName.Rows) 
       { 
        if (st_Time.Trim() != "" && end_Time.Trim() != "") 
        { 
         tsStart = new TimeSpan(DateTime.Parse(st_Time.Trim()).Hour, DateTime.Parse(st_Time.Trim()).Minute, DateTime.Parse(st_Time.Trim()).Second); 
         tsEnd = new TimeSpan(DateTime.Parse(end_Time.Trim()).Hour, DateTime.Parse(end_Time.Trim()).Minute, DateTime.Parse(end_Time.Trim()).Second); 
        } 
        else 
        { 
         tsStart = new TimeSpan(09, 00, 00); 
         tsEnd = new TimeSpan(17, 30, 0); 
        } 

      // iterate in all CSR name 
        if (row["party1name"] != DBNull.Value) 
        { 
         strCSRName = row["party1name"].ToString(); 

         // iterate in all time interval like 08:00:00 to 08:30:00, 08:30:00 to 09:00:00, 09:00:00 to 09:30:00.....17:00:00 to 17:30:00 
         while (tsStart <= tsEnd) 
         { 
          if (!flag) 
          { 
           tsStart = new TimeSpan(tsStart.Hours, tsStart.Minutes, int.Parse("01")); 
          } 
          flag = false; 

          StartTime = tsStart.ToString(); 
          tsStart = tsStart.Add(new TimeSpan(00, 30, 00)); 
          EndTime = (tsStart.Hours >= 10 ? tsStart.Hours.ToString() : ("0" + tsStart.Hours.ToString())) + ":" + (tsStart.Minutes >= 10 ? tsStart.Minutes.ToString() : ("0" + tsStart.Minutes.ToString())) + ":00"; 

          strSql = "select (select count(*) as incoming from " + tableName + " where direction='I' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) >='" + StartTime + "' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) <='" + EndTime + "' "; 
          strSql = strSql + "and Is_Internal=0 and continuation=0 and RIGHT(convert(varchar,[call duration]),8)<> '00:00:00' "; 
          strSql = strSql + "and party1name='" + strCSRName + "') as incoming, "; 

          strSql = strSql + "(select count(*) as OutGoing from " + tableName + " "; 
          strSql = strSql + "where direction='O' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) >='" + StartTime + "' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) <='" + EndTime + "' "; 
          strSql = strSql + "and Is_Internal=0 and continuation=0 and party1name not in ('Voice Mail') "; 
          strSql = strSql + "and party1name='" + strCSRName + "') as OutGoing, "; 

          strSql = strSql + "(select count(*) as CallTransfer from " + tableName + " "; 
          strSql = strSql + "where continuation=1 and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) >='" + StartTime + "' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) <='" + EndTime + "' "; 
          strSql = strSql + "and RIGHT(convert(varchar,[call duration]),8)<> '00:00:00' and party1name not in ('Voice Mail') "; 
          strSql = strSql + "and party1name='" + strCSRName + "') as CallTransfer; "; 

          strSql = strSql + "SELECT count(*) as UnansweredCalls_DuringBusinessHours from "; 
          strSql = strSql + tableName + " where direction='I' and " + Environment.NewLine; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) >='" + StartTime + "' and "; 
          strSql = strSql + "CONVERT(datetime,right([Call Start],8)) <='" + EndTime + "' "; 
          strSql = strSql + "and RIGHT(convert(varchar,[call duration]),8)= '00:00:00' and [Ring duration]>0 " + Environment.NewLine; 
          strSql = strSql + "and party1name='" + strCSRName + "'" + Environment.NewLine; 

          if (Business.CurrentCountry.CountryCode == "US" || Business.CurrentCountry.CountryCode == "MX" || Business.CurrentCountry.CountryCode == "ES" || Business.CurrentCountry.CountryCode == "NL" || Business.CurrentCountry.CountryCode == "PL") 
          { 
           strSql = strSql + " and Park_Time=0"; 
          } 

          strSql = strSql + Environment.NewLine; 

          DataSet oDS = Common.GetDataSet(strSql, ""); 

          if (oDS.Tables.Count > 0) 
          { 
           if (oDS.Tables[0].Rows.Count > 0) 
           { 
            dr = srcTable.NewRow(); 
            dr[0] = strCSRName; 
            dr[1] = StartTime + "--" + EndTime; 
            if (oDS.Tables[0].Rows[0]["incoming"] != DBNull.Value) 
            { 
             dr[2] = oDS.Tables[0].Rows[0]["incoming"].ToString(); 
             incall = incall + int.Parse(oDS.Tables[0].Rows[0]["incoming"].ToString()); 
            } 
            else 
            { 
             dr[2] = "0"; 
            } 

            if (oDS.Tables[0].Rows[0]["OutGoing"] != DBNull.Value) 
            { 
             dr[3] = oDS.Tables[0].Rows[0]["OutGoing"].ToString(); 
             outcall = outcall + int.Parse(oDS.Tables[0].Rows[0]["OutGoing"].ToString()); 
            } 
            else 
            { 
             dr[3] = "0"; 
            } 

            if (oDS.Tables[0].Rows[0]["CallTransfer"] != DBNull.Value) 
            { 
             dr[4] = oDS.Tables[0].Rows[0]["CallTransfer"].ToString(); 
             transfercall = transfercall + int.Parse(oDS.Tables[0].Rows[0]["CallTransfer"].ToString()); 
            } 
            else 
            { 
             dr[4] = "0"; 
            } 
           } 

           if (oDS.Tables[1].Rows.Count > 0) 
           { 
            if (oDS.Tables[1].Rows[0]["UnansweredCalls_DuringBusinessHours"] != DBNull.Value) 
            { 
             dr[5] = oDS.Tables[1].Rows[0]["UnansweredCalls_DuringBusinessHours"].ToString(); 
             totmisscall = totmisscall + int.Parse(oDS.Tables[1].Rows[0]["UnansweredCalls_DuringBusinessHours"].ToString()); 
            } 
           } 
           srcTable.Rows.Add(dr); 
          } 
         } 
        } 
       } 
      } 

      txtIncomming.Text = incall.ToString(); 
      txtOutGoing.Text = outcall.ToString(); 
      txtCallTransfer.Text = transfercall.ToString(); 
      txtMissCall.Text = totmisscall.ToString(); 
      //srcTable.DefaultView.Sort = "[CSR Name], [Time]"; 

      DataSet oDs = new DataSet(); 
      oDs.Tables.Add(srcTable); 

      this.outlookGrid1.ExpandIcon = global::BBA.Properties.Resources.Collapse; 
      this.outlookGrid1.CollapseIcon = global::BBA.Properties.Resources.Expand; 

      if (srcTable.Rows.Count > 0) 
      { 
       outlookGrid1.BindData(oDs, "data"); 
       View = "BoundCategory"; 
       DataGridViewCellEventArgs evt = new DataGridViewCellEventArgs(0, -1); 
       object sender = new object(); 
       dgResult_CellClick(sender, evt); 
       outlookGrid1.ExpandAll(); 
      } 
      else 
      { 
       outlookGrid1.Rows.Clear(); 
       MessageBox.Show("No data found"); 
      } 
     } 

那麼我在做什麼?我正在讀取一個CSV文件,然後將CSV文件數據插入數據庫表中,稍後用條件獲取這些數據,並以2個循環形成實際數據。

上述代碼和過程工作正常,但速度很慢。我被告知僅使用LINQ來讀取csf文件數據並形成輸出。雖然在LINQ中我很弱,所以需要您的幫助來形成正確的linq查詢以獲得準確的輸出。

這種方式我嘗試到目前爲止形成的LINQ查詢,但老實說,無法正確安排它。這是我的linq查詢,需要添加更多才能成爲完整的代碼。 在這裏,我正在粘貼我工作的linq查詢,它很慢但沒有拋出錯誤。

void Main() 
{ 
    var csvlines = File.ReadAllLines(@"M:\smdr(backup08-06-2015).csv"); 
    var csvLinesData = csvlines.Skip(1).Select(l => l.Split(',').ToArray()); 

    var users = csvLinesData.Select(data => new User 
    { 
     CSRName = data[12], 
     Incomming = csvLinesData.Count(w => w[4] == "I" 
             && w[8] == "0" 
             && w[10] == "0" 
             && w[1].ToString().Substring(w[1].ToString().Length-8)!="00:00:00"), 

     outgoing = csvLinesData.Count(w => w[4] == "O" 
             && w[8] == "0" 
             && w[10] == "0" 
             && w[1].ToString().Substring(w[1].ToString().Length-8)!="00:00:00"), 

    }) 
    .Where(u => !u.CSRName.Contains("VM") && u.CSRName != "Voice Mail").OrderBy(u=> u.CSRName) 
    .ToList(); 
    users.Dump(); 
} 

class User 
{ 
    public string CSRName; 
    public int outgoing; 
    public int Incomming; 

} 

所以我請求所有誰在LINQ的專家請看看我的C#代碼,並幫我組成一個全功能的LINQ查詢其帶來同樣的輸出,而不在迭代循環。

這裏是我的csv文件url http://s000.tinyupload.com/?file_id=22225722172003614028任何人都可以下載。只要點擊test.csv文件鏈接,如果任何人有興趣。謝謝

回答

2

我個人認爲Linq將比一個良好的for循環快得多。 (除非你正在利用PLinq)我認爲更大的問題是你的數據模型可能需要不同的設計。我會做的是創建一個新的類,它只代表一行和它的重要細節。

class CallInformation { 
    public DateTime CallStart { get; private set; } 
    public Boolean IsOutGoing {get; private set; } 
    public String CSRName {get; private set; } 
    public int InComingCount { get; set; } 
    public int OutgoingCount { get; set; } 

    public CallInformation(String[] parts) { 
     IsOutGoing = parts[4] == "O"; 
     CallStart = DateTime.Parse(parts[0]); 
     CSRName = parts[12]; 
    } 
    //... Continue with the important properties 
} 

現在,一個IO流也可以提高性能,但是爲了清楚起見,我將排除這一點。在您搜索的時候,排序和合並您的項目往往要快得多。如果你可以避免重串比較/創建,你通常會大大提高性能。

從你

Dictionary<String, CallInformation> callDictionary = new Dictionary<String,CallInformation>(); 
var csvLinesData = csvlines.Skip(1).Select(l => l.Split(',').ToArray()); 

foreach(string[] parts in csvLinesData) { 
    //Then place this call into a sortedlist or Dictionary. 
    //Here i am counting up the incoming and outgoing calls. 
    if(callDictionary.containsKey(parts[12])) { 
     if(parts[4] == "I") { 
      callDictionary[parts[12]].InComingCount++; 
     } else { 
      callDictionary[parts[12]].OutGoingCount++; 
     } 
    } else { 
     //Construct your new object based on this row. 
     CallInformation call = new CallInformation(parts); 
     callDictionary.add(call.CSRName, call); 
    } 
} 

排序後的列表,這部分可以根據開始時間或其他字段排序。管理你的輸出。我個人無法圍繞您正在分組和處理的確切方法進行包裝。我個人認爲你的表現是基於你正在查詢你的數據集以獲取永遠不會出現的信息。但請讓我知道你如何分組信息。我認爲這更多的是你如何分組信息。

如果您試圖根據持續時間分段撥打電話,則可以使用DateTime部分找出字典中的哪個「存儲桶」來放置它,而不是上面完成的CSR名稱(通過調整call.CSRName,containsKey[12]),您可以改爲創建持續時間字符串。通過使用日期時間對象,您可以根據時間差異進行比較,而不是字符串比較。

拉數據從這個集合你實際上要使用Linq的你是因爲長相來執行

查詢像

callDictionary.Where((keyValuePair) => { return keyValuePair.Value.CSRName != "VM" && keyValuePair.Value.CSRName != "VoiceMail"; }).OrderBy(o.Value.StartTime); 

的排序依據子句是真的取決於你的我們已經「開始」了,我們已經可以按照開始時間進行排序,以獲得更好的控制,您希望StartTime成爲TimeDuration的開始。任何一個特定的項目,這將是大致正確的。您也可以通過CSRName添加另一個OrderBy進行排序。

+0

我只是試圖做所有的LINQ。 – Thomas

+0

問題是,LINQ只是不一定更快。我可以鞭策一些邏輯,但LINQ往往是一些非常聰明的循環建設。 – Nathan

+0

你還在處理這個問題嗎?我沒有太多時間來創建LINQ查詢,但是如果你一直在研究它們,LINQ本身通常是ForEach Loops。這就是爲什麼我建議按照順序排列收藏。 – Nathan

相關問題