具有实体框架的ASP Web API控制器非常慢且结果奇怪

时间:2016-04-30 12:50:07

标签: entity-framework asp.net-web-api

我有3个表OPERATORS(20条记录),SALES(7000条记录),SALES_DETAIL(36000条记录)。

在Visual Studio 2015中使用Entity Framework和数据库优先方法我想创建一个Web Api控制器,它只返回当前打开的销售(CLOSE_DATA==null)的运算符:

public  IQueryable <OPERATORS> GetOPERATORS()
{
    IQueryable<OPERATORS> c = from co in db.SALES
                              join op in db.OPERATORS on co.ID_OP equals op.ID
                              where co.CLOSE_DATA == null
                              select op;
    return c;
}

在SQL Server Management Studio中运行的等效SQL会返回正确的结果,在0.00毫秒内返回3条记录。

select o.* 
from OPERATORS o 
inner join SALES c on c.ID_OP = o.id 
where c.CLOSE_DATA is null

在浏览器api控制器中返回大量数据并且浏览器几乎冻结,在fiddler中答案非常慢,我可以看到SALES_DETAIL中我没有包含在我的查询中的数据?

如果我更改控制器中的操作以返回Long并返回c.Count(),则结果是正确的:3。

为什么包含SALES_DETAIL,为什么查询非常慢?

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以在此处尝试2个选项。

选项1:您可以停用 lazy loading whole project,如下所示。

public YourContext()
{
    this.Configuration.LazyLoadingEnabled = false;
}

选项2 关闭 lazy loading以获取特定的导航属性,如下所示。通过制作SaleDetails属性non-virtual

来关闭
public class YourModel 
{  
    public int Id { get; set; }  
    public string Name { get; set; }  

    public ICollection<SaleDetail> SaleDetails { get; set; }  
}

以下是一个有用的链接:Lazy Loading

答案 1 :(得分:1)

您可以通过添加AsNoTracking优化/改进您的查询:

实体框架提供了许多性能调优选项,可帮助您优化应用程序的性能。其中一个调整选项是.AsNoTracking()

所以你的查询将如下所示:

var query = from co in db.SALES.AsNoTracking()
               join op in db.OPERATORS.AsNoTracking()
               on co.ID_OP equals op.ID
               where co.CLOSE_DATA == null
               select op;
   return query.ToList();

要使该呼叫无阻塞,您可以利用EF中的异步调用:

public async Task<IList<OPERATORS>> GetOPERATORS()
{
    var query = from co in db.SALES.AsNoTracking()
                   join op in db.OPERATORS.AsNoTracking()
                   on co.ID_OP equals op.ID
                   where co.CLOSE_DATA == null
                   select op;
       return await query.ToListAsync();
}