1

当我尝试循环遍历结果以创建 Xelement 时,我的 linq 查询变慢,稍后我会根据 XElement 处理 XSLT。

这是我的代码

public override XElement Search(SearchCriteria searchCriteria)
    {
        XElement root = new XElement("Root");
        using (ReportOrderLogsDataContext dataContext = DataConnection.GetLinqDataConnection<ReportOrderLogsDataContext>(searchCriteria.GetConnectionString()))
        {
            try
            {


                IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts
                              where
                                  (a.CreateDt.HasValue &&
                                   a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
                                   a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))
                              select a;

                if (!string.IsNullOrEmpty(searchCriteria.AgentNumber))
                {
                    results = results.Where(request => request.LgAgentNumber == searchCriteria.AgentNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.AgentTitle))
                {
                    results = results.Where(a => a.LgTitle == searchCriteria.AgentTitle);
                }
                if (!string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber))
                {
                    results = results.Where(a => a.QuotePolicyNumber == searchCriteria.QuotePolicyNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
                {
                    results = results.Where(a => a.LgInsuredName.Contains(searchCriteria.InsuredName));
                }

                foreach (var match in results) // goes slow here, specifically times out before evaluating the first match when results are too large.
                {
                    DateTime date;
                    string strDate = string.Empty;
                    if (DateTime.TryParse(match.CreateDt.ToString(), out date))
                    {
                        strDate = date.ToString("MM/dd/yyyy");
                    }

                    root.Add(new XElement("Record",
                                          new XElement("System", "Not Supported"),
                                          new XElement("Date", strDate),
                                          new XElement("Agent", match.LgAgentNumber),
                                          new XElement("UserId", match.LgUserId),
                                          new XElement("UserTitle", match.LgTitle),
                                          new XElement("QuoteNum", match.QuotePolicyNumber),
                                          new XElement("AddressLine1", match.AddressLine1),
                                          new XElement("AddressLine2", match.AddressLine2),
                                          new XElement("City", match.City),
                                          new XElement("State", match.State),
                                          new XElement("Zip", match.Zip),
                                          new XElement("DriverName", string.Concat(match.GivenName, " ", match.SurName)),
                                          new XElement("DriverLicense", match.LicenseNumber),
                                          new XElement("LicenseState", match.LicenseState)));
                    ;
                }
            }
            catch (Exception es)
            {

                throw es;
            }
        }
        return root;
        // return GetSearchedCriteriaFromStoredPocedure(searchCriteria);
    }

我认为有更好的方法将结果对象转换为 XElement。处理视图本身只需要大约 2 秒。尝试遍历结果对象会导致超时,即使没有返回许多结果。

任何帮助,将不胜感激。

谢谢!

-詹姆士

2012 年 7 月 10 日修订

问题不在于 linq 查询本身,而在于指定日期范围时视图的执行。单独执行视图大约需要 4-6 秒。当使用较小的日期范围(07/05/2012 - 07/10/2012)时,视图大约需要 1:30。有没有人对如何在指定的日期范围内提高查询性能有任何建议。如果我得到所有结果并循环检查日期,它会更快。

IE

    IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts select a;

                foreach (var match in results) //results only takes 3 seconds to enumerate, before would timeout
                {
                    // eval search criteria date here.
                }

我可以像上面建议的那样对其进行编码,但是有人有更好的方法吗?

4

3 回答 3

2

数据库表现如何?最简单的测试是运行一个示例查询 - 一个将从数据库中检索您需要的数据的查询,只是为了测试数据库索引和性能 - 因为在 99% 的情况下这是导致缓慢的原因。

我猜想这种缓慢正在发生,因为

  • 您正在从数据库中迭代,而不是预先检索所有行,并且
  • 您在恶劣的WHERE条件下选择(您的索引是否正确?)

首先,调用ToList获取结果以确定缓慢发生在数据库中,而不是在 XML 构造中

if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
{
    //...
}    
var matches = results.ToList();    
foreach (var match in matches) 
{
    //...

假设var matches = results.ToList()非常慢,我会看看WHERE子句中的函数

(a.CreateDt.HasValue &&
a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))

检查它们是否没有为每一行执行。

如果您使用 SQL Server,请运行 Profiler(在工具菜单中)以跟踪 LINQ-to-SQL 的 SQL。

于 2012-07-09T22:40:59.007 回答
1

当然,在 linq 之外进行转换。条件在 Linq 表达式运行期间不会改变。

根据您发布的内容,我做了这个例子:

var begin = Convert.ToDateTime(searchCriteria.BeginDt);
var end = Convert.ToDateTime(searchCriteria.EndDt);

var results = from a in searchList
              where ((a.CreateDt.HasValue &&
                      a.CreateDt >= begin &&
                      a.CreateDt <= end)
                      && (string.IsNullOrEmpty(searchCriteria.AgentNumber) || a.LgAgentNumber == searchCriteria.AgentNumber)
                      && (string.IsNullOrEmpty(searchCriteria.AgentTitle) || a.LgTitle == searchCriteria.AgentTitle)
                      && (string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber) || a.LgTitle == searchCriteria.QuotePolicyNumber)
                      && (string.IsNullOrEmpty(searchCriteria.InsuredName) || a.LgInsuredName.Contains(searchCriteria.InsuredName))
                     )
                        select a;

也许这对你有帮助。

为了测量时间,我使用了以下方法:

var watch = new Stopwatch();
watch.Start();
var arr = results.ToArray();  // force evaluation of linq
watch.Stop();
var elapsed = watch.ElapsedTicks;

似乎更改后的查询已经平均快了大约 30-40%,但我只是做了一些运行。

于 2012-07-09T20:16:32.927 回答
1

我建议做一些实验:

一。
放一个

int count = results.Count();

foreach之前,看看这是否需要很长时间。

二。
离开Count()调用,看看foreach是否仍然很慢。如果速度很快,则表明与数据库的初始连接很慢。

正如其他人所建议的那样 - 看看您在数据库中的查询执行情况(实际上是在数据库中输入,没有 c#)。

您还可以发布 SHOW TABLE 结果,以便社区可以检查索引并帮助您进行修复。

于 2012-07-10T07:47:10.377 回答