在foreach循环中计数,最佳实践
本文关键字:最佳 foreach 循环 | 更新日期: 2023-09-27 18:13:18
我一直致力于在foreach循环中获得计数记录。我将需要在一个页面上运行许多这些计数。我正在寻找最有效的方法来做到这一点。
我已经走了这么远,但我不确定我是否走在正确的道路上。如果是,我怎么把数据放到我的视图中。
视图模型
public class AgtLeadStatsListVM
{
public string LoanAgent { get; set; }
public DateTime LeadDate { get; set; }
public int LeadDailyCt { get; set; }
public int LeadWeeklyCt { get; set; }
public int LeadMTDCt { get; set; }
public int LeadYTDCt { get; set; }
public IEnumerable<MWFUser> AgentList { get; set; }
public virtual WebLead Lead { get; set; }
}
控制器
var model = new AgtLeadStatsListVM();
{
// Get Selected Agent's Information
var AgentList = from l in db.MWFUsers
where (l.UserTitle == "Banker"
select l;
foreach (var agent in AgentList)
{
// Daily Lead Count
var LeadDailyCt = db.WebLeads.Count(x => (x.LoanAgent == agent.UserEmail)
&& (x.LeadDate >= todayDate && x.LeadDate <= todayEndDay));
// Weekly Lead Count
var LeadWeeklyCt = db.WebLeads.Count(x => (x.LoanAgent == agent.UserEmail)
&& x.LeadDate >= firstOfWeek
&& x.LeadDate <= todayEndDay);
// Monthly Lead Count
var LeadMTDCount = db.WebLeads.Count(x => (x.LoanAgent == agent.UserEmail)
&& x.LeadDate >= firstOfMonth
&& x.LeadDate <= todayEndDay);
// YTD Lead Count
var LeadYTDCount = db.WebLeads.Count(x => (x.LoanAgent == agent.UserEmail)
&& x.LeadDate >= firstOfMonth
&& x.LeadDate <= todayEndDay);
}
}
视图@model LoanModule.ViewModels.AgtLeadStatsListVM
<div>
@foreach (var item in Model.AgentList)
{
<p>@Model.LoanAgent</p>
<p>@Model.LeadDailyCt</p>
<p>@Model.LeadWeeklyCt</p>
<p>@Model.LeadMTDCt</p>
<p>@Model.LeadYTDCt</p>
}
我在我的视图上收到这个错误:对象引用没有设置为对象的实例。(在线:@foreach (var item in Model.AgentList))
我错过了什么?
谢谢。
var model = new AgtLeadStatsListVM();
末尾的分号表示在该行之后您不再处于对象初始化器中。您可能正在尝试的语法更类似于以下内容:
var agents =
from l in db.MWFUsers
where l.UserTitle == "Banker"
select l;
var model = new AgtLeadStatsListVM
{
// Get Selected Agent's Information
AgentList = agents.ToList(),
// Daily Lead Count
LeadDailyCt = agents.Sum(a => db.WebLeads.Count(
x => (x.LoanAgent == a.UserEmail)
&& (x.LeadDate >= todayDate && x.LeadDate <= todayEndDay)))
// ...
}
顺便说一下,如果您想在一次往返中获得所有这些信息,您可以使用基于group by
的技巧。
var model =
(from agent in agents
let webLeads = db.WebLeads.Where(x => x.LoanAgent == agent.UserEmail)
group new{agent, webLeads} by 0 into g
select new AgtLeadStatsListVM
{
// Get Selected Agent's Information
AgentList = g.Select(e => e.agent).ToList(),
// Daily Lead Count
LeadDailyCt = g.Sum(e => e.webLeads.Count(x => x.LeadDate >= todayDate && x.LeadDate <= todayEndDay)),
// ...
}).FirstOrDefault();
更新从你的评论听起来这更像是你想要的:
var model =
(from agent in agents
let webLeads = db.WebLeads.Where(x => x.LoanAgent == agent.UserEmail)
select new AgtLeadStatsListVM
{
// Get Selected Agent's Information
LoanAgent = agent.UserEmail,
// Daily Lead Count
LeadDailyCt = webLeads.Count(x => x.LeadDate >= todayDate && x.LeadDate <= todayEndDay),
// ...
}).ToList();
和你的视图代码:
@model IEnumerable<LoanModule.ViewModels.AgtLeadStatsListVM>
<div>
@foreach (var item in Model)
{
<p>@item.LoanAgent</p>
<p>@item.LeadDailyCt</p>
<p>@item.LeadWeeklyCt</p>
<p>@item.LeadMTDCt</p>
<p>@item.LeadYTDCt</p>
}
AgentList
属性应该从你的模型中完全移除
我在我的视图上收到这个错误:对象引用未设置为an对象的实例。(在线:@foreach (var item in)Model.AgentList)
AgentList
为空。
而且,你还没有正确初始化你的模型。
具体来说,这行代码
var model = new AgtLeadStatsListVM();
创建一个AgtLeadStatsListVM
类型的新对象,其中
-
LoanAgent
为null -
LeadDate
1/1/0001 12:00:00 am -
LeadDailyCt
为0 -
LeadWeeklyCt
为0 -
LeadMTDCt
为0 -
LeadYTDCt
为0 -
AgentList
为null -
WebLead
is Lead
默认值,因为您没有设置任何值。可能,您想要使用对象初始化器,在那里您不需要();
。我们这样写:
var model = new AgtLeadStatsListVM
{
LoadAgent = "Name of the LoadAgent",
LeadDate = DateTime.Now.Utc,
LeadDailyCt = agents.Sum(a => db.WebLeads.Count(
x => (x.LoanAgent == a.UserEmail)
&& (x.LeadDate >= todayDate && x.LeadDate <= todayEndDay)))
// Do the same for the rest of the corresponding properties.
}
我将忽略您得到的错误(请参阅其他答案),并且只参考最佳实践和计算部分问题的最有效方法。
最有效的方法(至少在我看来)是对结果使用一些缓存技术并每天更新缓存(因为您使用的最大分辨率是每天)。显然,选择合适的缓存机制取决于您的应用程序。它可以从在应用程序启动时将一些数据存储在静态变量中,到运行专用的Redis服务器(或任何其他快速数据结构存储)。这里的底线是:尽量减少对DB的查询数量,并缓存任何合适的数据。