我的 SQL Server 数据库中有一个表,其中包含许多列,但重要的列是 LoggedState
和 InteractionType
。
我需要找到中断座席的数量和空闲座席的数量。
我尝试过的
SqlCommand GraphCmd = new SqlCommand("getAgentStatues", Graphsqlcon);
SqlParameter tdate = new SqlParameter();
GraphCmd.CommandType = CommandType.StoredProcedure; ;
SqlDataAdapter DAGraph = new SqlDataAdapter(GraphCmd);
DataSet DSGraph = new DataSet();
DSGraph.Clear();
DAGraph.Fill(DSGraph);
DataTable DTgraph = new DataTable();
DTgraph = DSGraph.Tables[0];
int numberOfBreakAgents = 0;
int numberOfIdelAgents = 0;
foreach (DataRow row in DTgraph.Rows)
{
String LoggedState = row["LoggedState"].ToString().Trim().ToLower();
String InteractionType = row["InteractionType"].ToString();
if (LoggedState == "break")
{
numberOfBreakAgents++;
}
else if ((LoggedState == "activo") && (row["InteractionType"] == DBNull.Value))
{
numberOfIdelAgents++;
}
}
它工作得很好,但我想问是否有一种方法(比如分组)来避免 foreach
语句
最佳答案
您可以使用 Linq 中的Group
函数:
var loggedStateGroups = dt.AsEnumerable().GroupBy(d => d["LoggedState"].ToString(), (group, row) => new
{
LoggedState = group,
AllCount = row.Count(),
NullCount = row.Where(r => r["InteractionType"] == DBNull.Value).Count()
});
这将按 LoggedState 进行分组,其中包含每个匹配行的计数 (AllCount
) 以及 InteractionType 为 DBNull.Value
的行的计数 (NullCount
)。
然后我们可以通过执行以下操作来选择我们想要的计数:
int numberOfBreakAgents = loggedStateGroups.Where(y => y.LoggedState == "break").First().AllCount;
int numberOfIdelAgents = loggedStateGroups.Where(y => y.LoggedState == "activo").First().NullCount;
请注意,我仅使用 First
假设您始终会得到结果。如果您并不总能得到结果,则应使用 FirstOrDefault
并执行 null 检查。
您可以在使用Group
之前进行过滤,方法是根据您的数据添加以下Where
。
.Where(r => r["LoggedState"].ToString() == "break" || r["LoggedState"].ToString() == "activo")
我已经使用以下设置对此进行了测试:
DataTable dt = new DataTable();
dt.Columns.Add("LoggedState");
dt.Columns.Add("InteractionType");
dt.Rows.Add("break", "inter1");
dt.Rows.Add("activo", DBNull.Value);
dt.Rows.Add("break", "inter1");
dt.Rows.Add("break", "inter2");
dt.Rows.Add("activo", "inter2");
我分别得到 numberOfBreakAgents
和 numberOfIdelAgents
的 3
和 1
。
编辑使用 FirstOrDefault:
如果您想执行上面提到的 null 检查,您可以将上面的两个 int
声明行替换为:
var breakAgents = loggedStateGroups.Where(y => y.LoggedState == "break").FirstOrDefault();
var idelAgents = loggedStateGroups.Where(y => y.LoggedState == "activo").FirstOrDefault();
int numberOfBreakAgents = breakAgents != null ? breakAgents.AllCount : 0;
int numberOfIdelAgents = idelAgents != null ? idelAgents.NullCount : 0;
这将采用第一个 LoggedState 为“break”的组,如果没有,则为 null
。然后,如果该组不为 null,则将 numberOfBreakAgents
分配给 AllCount
属性;如果为 null,则分配 0
属性。
对 numberOfIdelAgents
执行类似的操作,只不过我们过滤“activo”组并使用 NullCount
属性,因为我们对 all 行,我们只对 InteractionType 为 DBNull.Value
的行感兴趣,这些行是我们在 NullCount
属性中捕获的。
如果结果集包含 LoggedState 为“activo”的零行或 LoggedState 为“break”的零行,则必须进行空检查。在这种情况下,.First()
将返回 null
并从中访问 AllCount
或 NullCount
将导致“序列不包含元素”异常。
使用以下 DataTable 定义将突出显示差异,因为它会导致使用 First()
的 numberOfBreakAgents
出现异常,但在使用时正确返回 0
FirstOrDefault
。
DataTable dt = new DataTable();
dt.Columns.Add("LoggedState");
dt.Columns.Add("InteractionType");
dt.Rows.Add("activo", "inter1");
dt.Rows.Add("activo", DBNull.Value);
dt.Rows.Add("activo", "inter1");
dt.Rows.Add("activo", "inter2");
dt.Rows.Add("activo", "inter2");
关于c# - 从数据表中提取两件事的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25136264/