【问题标题】:jQuery/Ajax call taking excruciating amount of time to completejQuery/Ajax 调用需要花费大量时间才能完成
【发布时间】:2013-05-06 20:45:46
【问题描述】:

下面是我在我的 ASP MVC 3 视图中为他们的typeahead.js 插件使用的 jQuery 代码。

        $('#typeahead').typeahead({
            source: function (term, process) {
                var url = '@Url.Content("~/Agent/GetAgents")';
                var agents = [];
                map = {};

                return ($.getJSON(url, { term: term }, function (data) {
                    $.each(data, function (i, item) {
                        map[item.Name] = item;
                        agents.push(item.Name);
                    });

                    process(agents);
                }));
            },
            highlighter: function (item) {
                var p = map[item];
                var display = ''
                             + "<div class='typeahead_wrapper'>"
                             + "<div class='typeahead_labels'>"
                             + "<div class='typeahead_primary'>" + p.Name + </div>
                             + "<i>LastFour:</i>" + p.LastFour + "</div>"
                             + "<div class='typeahead_third'>" + "<i>Agent IDs:</i> " + p.AgentIds + "</div>"
                             + "</div>"
                             + "</div>";

                return display;
            },
            updater: function (item) {
                window.location.href = ("/Agent/Details/" + map[item].sNumber);                    
            }             
        });

代码在控制器中调用此GetAgents 方法。整个过程按预期完成,但完成此过程几乎需要一分钟。

    [HttpGet]
    public JsonResult GetAgents(string term)
    {
        term = term.ToUpper();

        var agents = (from a in db.Agent
                      where a.FirstName.Contains(term) ||
                            a.LastName.Contains(term)
                      select a).AsEnumerable()
                             .Select(x => new
                             {
                                 Name = x.FirstName + " " + x.LastName,
                                 sNumber = x.sNumber,
                                 LastFour = x.DisplayTaxId,
                                 AgentIds = String.Join(", ", from b in db.sNumberToAgentId
                                                             where b.sNumber == x.sNumber
                                                             select b.AgentId)
                             });

        var corps = (from a in db.Agent
                      where a.CorporateName.Contains(term) 
                      select a).AsEnumerable()
                        .Select(x => new
                        {
                            Name = x.FirstName + " " + x.LastName,
                            sNumber = x.sNumber,
                            LastFour = x.DisplayTaxId,
                            AgentIds = String.Join(", ", from b in db.sNumberToAgentId
                                                         where b.sNumber == x.sNumber
                                                         select b.AgentId)
                        });

        return new JsonResult()
        {
            Data = (agents.Union(corps).ToArray()),
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    } 

单步执行代码,问题似乎出在这部分。有谁知道加快此类呼叫的方法或为什么会发生这种情况?

        return new JsonResult()
        {
            Data = (agents.Union(corps).ToArray()),
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };

编辑

我将查询更改为下面的这个结构,但是现在我收到了OutOfMemory Exception

        var agents = (from a in db.Agent
                     from b in db.sNumberToAgentId
                     join b in db.sNumberToAgentId on a.sNumber equals b.sNumber into apm
                     where a.FirstName.Contains(term) || a.LastName.Contains(term)
                     select new
                                {
                                    Name = a.FirstName + " " + a.LastName,
                                    sNumber = a.sNumber,
                                    LastFour = a.DisplayTaxId,
                                    AgentIds = b.AgentId
                                }).ToList();

【问题讨论】:

  • 对您的 SQL 查询进行基准测试。 Data = (agents.Union(corps).ToArray())... 行是执行查询的内容,所以它在那里被延迟是有道理的。
  • 为什么where a.FirstName.Contains(term) || a.LastName.Contains(term) || a.CorporateName.Contains(term) 的选择还不够?
  • 我很好奇这会生成什么样的 SQL,以及为什么你要从 SQL 语法转向构造函数语法(或任何它的名字),而不是在后者中全部完成并避免 AsEnumerable在进行选择投影之前。我想知道这种格式是否导致投影未应用于 SQL 调用,但后来评估意味着返回的数据多于必要的数据。
  • 不太清楚你所说的“基准测试”我的 SQL 查询是什么意思。如果您的意思是与我们在此站点上进行的其他操作进行比较,则等待时间甚至无法比较。大多数都在几毫秒内完成,但这需要将近一分钟。
  • 我认为他的意思是从该查询中获取生成的 SQL 语句并在您的 SQL DB 上运行它以查看执行需要多长时间。实际上,生成的 SQL 可能足以发现问题,但也无妨。他们可能会建议您需要索引等。

标签: asp.net-mvc asp.net-mvc-3 jquery bootstrap-typeahead


【解决方案1】:

老实说,考虑到重用的可能性,您可能会考虑在存储过程中执行所有这些操作,然后使用您的“term”参数调用它。

如果这不可行,我建议您查看您的数据源是否有很多列 - 您当前的语法可能不适合优化的 SQL。通常,您的 Select 可以用作投影,仅带回您从中提取数据的列。

你可以试试这个,但它未经测试。我无法立即想到提前进行连接以消除 Select 投影中的子查询的语法,但也许其他人可以提供帮助。

var results = db.Agent
  .Where(a => a.CorporateName.Contains(term) || a.FirstName.Contains(term) || a.LastName.Contains(term))
  .Select(x => new {
    Name = x.FirstName + " " + x.LastName,
    sNumber = x.sNumber,
    LastFour = x.DisplayTaxId,
    AgentIds = String.Join(", ", from b in db.sNumberToAgentId
                                 where b.sNumber == x.sNumber
                                 select b.AgentId)
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2022-12-23
    相关资源
    最近更新 更多