【问题标题】:MVC - Count in a foreach loop, best practiceMVC - 在 foreach 循环中计数,最佳实践
【发布时间】:2015-09-19 06:31:30
【问题描述】:

我一直致力于在 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(Model.AgentList 中的变量项))

我错过了什么?

谢谢。

【问题讨论】:

  • 为了“更好的实践”,我会创建一个IEnumerable&lt;AgtLeadStatsListVM&gt; BuildAgentList(string title) 的函数并正确实现它。这将很容易看出在执行var model = new AgtLeadStatsListVM(); model.AgentList = BuildAgentList("Banker"); 时主要的“断开”问题是什么。 NPE 看起来是因为不了解 C# 属性是如何设置的。
  • 此外,后续属性的多重性都是错误的 - 这些可能应该是每个生成的“代理”对象的一部分。

标签: c# asp.net-mvc foreach


【解决方案1】:

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();

更新

从你的 cmets 看来,这更像是你想要的:

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 属性应该从您的模型中完全删除。

【讨论】:

  • 谢谢。我几乎有这个工作!视图中代理的 foreach 循环返回所有代理的总和,而不仅仅是那个特定的代理。我试图删除语句开头的总和,但是如何引用代理列表? agent.Sum(a => db.WebLeads.Count( x => (x.LoanAgent == a.UserEmail) && (x.LeadDate >= todayDate && x.LeadDate
  • @Daniela:当你说“那个特定的代理人”时,你是如何识别那个代理人的? UserTitle = "Banker" 是否足以将您的结果限制为您正在寻找的代理? (顺便说一句,我强烈建议您对主键和外键使用数字 ID 值。通过魔术字符串 UserTitle 进行查询并在 LoanAgent == UserEmail 上连接表可能不是一个好主意。)
  • 由 x.LoanAgent == a.UserEmail 提供。这个项目的发展方式,起初不需要外键(代理只是一个与任何东西无关的电子邮件地址)。因此,对于代理人 John Doe,我正在寻找他在一天、一周、一个月和一年内被分配了多少潜在客户。我正在为列表中的每个代理查找该号码。感谢您的帮助...边走边学。
  • @Daniela:如果您想为列表中的每个代理提供这些数字,那么您需要重新设计您的 Vm 类:现在它将 AgentList 作为一个属性,而将数字作为其他属性.我猜你希望你的模型是一个对象列表,每个对象都有一个代理名称和计数。
  • @Daniela:查看我的编辑。当您尝试为数据库中的一堆不同对象获取数据时,您绝对不想在for 循环中执行此操作,因为这将导致与您拥有的项目一样多的数据库往返在您的列表中。相反,构建一个查询,它将在一次往返中为您提供您正在寻找的所有数据
【解决方案2】:

我的视图收到此错误:对象引用未设置为 对象的实例。 (在线:@foreach(var item in 模型.AgentList))

AgentList 为空。

此外,您还没有正确初始化模型。

具体就是这行代码

var model = new AgtLeadStatsListVM();

创建一个AgtLeadStatsListVM 类型的新对象,其中

  • LoanAgent 为空
  • LeadDate 1/1/0001 12:00:00 AM
  • LeadDailyCt 为 0
  • LeadWeeklyCt 为 0
  • LeadMTDCt 为 0
  • LeadYTDCt 为 0
  • AgentList 为空
  • WebLead 是领导

默认值,因为您没有设置任何值。可能你想使用对象初始化器,你不需要();。我们只是这样写:

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.
}

【讨论】:

  • 正确!您提供的代码中没有设置。
【解决方案3】:

我将忽略您遇到的错误(请参阅其他答案)并仅参考 最佳实践和最有效的方法来计算问题的一部分

最有效的方法(至少在我看来)是对结果使用一些缓存技术并每天更新缓存(因为您使用的最大分辨率是每天)。显然,选择合适的缓存机制取决于您的应用程序。它可以从在应用程序启动时将一些数据存储在静态变量中,到运行专用的Redis server(或任何其他快速数据结构存储)。这里的底线是:尽量减少对 DB 的查询次数并缓存任何合适的数据。

【讨论】:

  • 一旦我的查询正常工作,我会调查的。这是一个小型的 n MVC 5 应用程序,内部用户少于 20 个。你知道任何可能有用的教程吗?
  • 这可能是一个不错的博客:stevescodingblog.co.uk/net4-caching-with-mvc
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 2018-09-23
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多