控制器中的Linq查询耗时太长

时间:2015-12-08 05:00:46

标签: asp.net asp.net-mvc linq asp.net-core-mvc entity-framework-core

我正在尝试学习一些关于最新的ASP.NET MVC 6,并且我有一个超级基本控制器,它执行linq查询,需要几分钟才能完成......

我在控制器中的方法是这样的:

public IActionResult GetSampleData(string date)
{
    string[] date = date.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
    int month = Convert.ToInt32(date[0]);
    int day = Convert.ToInt32(date[1]);
    int year = Convert.ToInt32(date[2]);

    var results =
        (from c in db.Book
         where c.Author.Equals("abc") 
         && (c.Created.CompareTo(new DateTime(year, month, day, 0, 0, 0)) >= 0) 
         && (c.Created.CompareTo(new DateTime(year, month, day, 23, 59, 59)) < 0)
         select new ObjectExample
         {
             Property1 = c.Field1,
             Property2 = c.Field2,
             Property3 = c.Field3,
             Property4 = c.Field4,
             Property5 = c.Field5,
         });

    return View(results.ToList());
}

嗯......这种方法要么非常慢(需要5分多钟才能完成),要么最终出现在这样的网关问题上:

  

HTTP错误502.3 - 错误网关

     

指定的CGI应用程序遇到错误和服务器   终止了这个过程

     

详细错误信息:

     

模块 httpPlatformHandler

     

通知 ExecuteRequestHandler

     

处理程序 httpPlatformHandler

     

错误代码 0x80072ee2

如果我在SQL Server上运行完全相同的查询,它甚至不需要一秒钟就能完成......结果只有7个条目。

我在这里缺少什么?此代码与我在另一个ASP.NET Web应用程序(另一个使用Silverlight)上的代码完全相同,并且它的工作速度非常快。

我有什么遗失的东西我应该看看吗?另外,有任何调试建议吗? (虽然这很直接......)

最后,这是我的appsettings.json,其中包含连接字符串

    {
      "Data": {
        "DefaultConnection": {
          "ConnectionString": "Data Source=DataBaseServerSample01;Initial Catalog=SampleDB;Integrated Security=True;App=EntityFramework"
        }

},
      "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
          "Default": "Verbose",
          "System": "Information",
          "Microsoft": "Information"
        }
      }
    }

请注意。我正在使用ASP.NET MVC6 RC(Update 1),我通过命令行使用脚手架创建了模型和控制器。

谢谢!

2 个答案:

答案 0 :(得分:1)

我想你在LinQToSql中寻找这个解决方案:

 var date = new DateTime(year, month, day);
 var results =
        (from c in db.Book
         where c.Author.Equals("abc") 
         && c.Created.Year == date.Year
         && c.Created.Month == date.Month
         && c.Created.Day == date.Day)
         select new ObjectExample
         {
             Property1 = c.Field1,
             Property2 = c.Field2,
             Property3 = c.Field3,
             Property4 = c.Field4,
             Property5 = c.Field5,
         });

正如你所见,我创建了一个日期对象,就像@Mark Schultheiss给你的建议一样。我只检查DateTime字段的日期部分。

老实说,还有另一种解决问题的可能性。您应该将SQL日期转换为String然后进行比较。只要LinqToSQL不支持像.ToString("yyyy-MM-dd")这样的功能,其中一种方法是使用 DbFunctions 检查this answer是否需要高性能。

答案 1 :(得分:1)

我建议您使用Glimpse一个开源诊断平台,您可以看到Entity Framework正在创建多少个查询,以及如何创建。除此之外,你可以使用 AsNoTracking() 对于只读的查询,它更具有性能。