我很难使用LINQ但在LINQ中并不好。
我开发了显示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文件网址http://s000.tinyupload.com/?file_id=22225722172003614028
,任何人都可以从这里下载。如果有兴趣的话,只需点击test.csv文件链接即可。感谢
答案 0 :(得分:2)
我个人认为Linq的速度远不如一个良好的for循环。 (除非你正在利用PLinq)我认为更大的问题是你的数据模型可能需要不同的设计。我要做的是创建一个代表一行及其重要细节的新类。
rule.color_class
现在IO流也可以提高性能,但为了清楚起见,我将排除它。在您进行排序和组合项目时,通常要快得多,而不是搜索。如果您可以避免繁重的字符串比较/创建,您通常会大大提高性能。
来自
的这一部分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
}
可以根据StartTime或其他字段对排序列表进行排序。这决定了你的输出。我个人无法绕过您正在分组和处理的确切方法。我个人认为您的表现是基于您查询数据集以获取永远不会出现的信息这一事实。但请告诉我您如何分组信息。我认为这更多的是你将如何分组信息。
如果您尝试根据持续时间进行呼叫,则可以使用DateTime部分找出&#34; bucket&#34;在字典中放置它,而不是我上面做的CSR名称(通过调整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);
}
}
和call.CSRName,
),您可以改为创建持续时间字符串。通过使用日期时间对象,您可以根据时差而不是字符串比较进行比较。
要从该集合中提取数据,您实际上希望使用Linq来执行该操作
像
这样的查询containsKey[12]
OrderBy子句真的取决于你的外表因为我们是&#34;顽抗&#34;事情我们可以按开始时间排序,为了获得更好的控制,你希望 callDictionary.Where((keyValuePair) => { return keyValuePair.Value.CSRName != "VM" && keyValuePair.Value.CSRName != "VoiceMail"; }).OrderBy(o.Value.StartTime);
成为TimeDuration的开始。任何1个特定项目,它将是近似正确的。您还可以添加另一个OrderBy,以便按StartTime
对其进行排序。
答案 1 :(得分:0)
类似下面的代码段
private static IEnumerable<MyData> Parse(String csvFile, bool hasHeaderLine = false, char separator = ',') {
return Read(csvFile)
.Skip(hasHeaderLine ? 1 : 0)
.Select(line => line.Split(separator, StringSplitOptions.None))
.Select(parts => new MyData(
parts[0],
DateTime.Parse(parts[1]),
TimeSpan.Parse(parts[2]),
uint.Parse(parts[3]),
uint.Parse(parts[4]),
uint.Parse(parts[5]),
uint.Parse(parts[6])
));
}
private static IEnumerable<String> Read(String csvFile) {
using (var reader = new StreamReader(csvFile)) {
String line;
while ((line = reader.ReadLine()) != null)
yield return line;
}
}
private class MyData {
private readonly string name;
private readonly DateTime startTime;
private readonly TimeSpan duration;
private readonly uint incommingCalls, outgoingCalls, callTransfers, missedCalls;
public MyData(string name, DateTime startTime, TimeSpan duration, uint incommingCalls, uint outgoingCalls, uint callTransfers, uint missedCalls) {
this.name = name;
this.startTime = startTime;
this.duration = duration;
this.incommingCalls = incommingCalls;
this.outgoingCalls = outgoingCalls;
this.callTransfers = callTransfers;
this.missedCalls = missedCalls;
}
public string Name => this.name;
public DateTime StartTime => this.startTime;
public TimeSpan Duration => this.duration;
public uint IncommingCalls => this.incommingCalls;
public uint OutgoingCalls => this.outgoingCalls;
public uint CallTransfers => this.callTransfers;
public uint MissedCalls => this.missedCalls;
public DateTime EndTime => this.startTime + this.duration;
}