如何提高EF中执行查询的速度

时间:2019-05-26 05:01:47

标签: c# asp.net-mvc entity-framework asp.net-mvc-4

方法FindByQueryAsNoTracking()的实现如下:

public IEnumerable<T> FindByAsNoTracking(Expression<Func<T, bool» predicate)
{
    IQueryable<T> query = Dbset.Where(predicate).AsNoTracking().AsQueryable();
        return query;
}

如果我们使用以下实现的FindByAsQuery

public IQueryable<T> FindByQuery(Expression<Func<T, bool» predicate)
{
    IQueryable<T> query = Dbset.Where(predicate).AsQueryable();
    return query;
}

速度会更好?

2 个答案:

答案 0 :(得分:2)

AsNoTracking(IQueryable)

返回一个新查询,其中返回的实体将不被缓存在DbContext或 ObjectContext 中。此方法通过调用基础查询对象的AsNoTracking方法来工作。如果基础查询对象没有AsNoTracking方法,则调用此方法将无效。

No Tracking Queries

  

5.1禁用更改跟踪以减少状态管理开销   您处于只读方案,并且希望避免以下操作的开销   将对象加载到ObjectStateManager中,可以发出“否   跟踪”查询。可以在查询中禁用更改跟踪   级别。

     

请注意,尽管通过禁用更改跟踪您可以有效地   关闭对象缓存。当您查询实体时,我们无法   通过拉出先前实现的查询来跳过实现   来自ObjectStateManager的结果。如果您反复查询   对于在相同上下文中的相同实体,您实际上可能会看到   启用更改跟踪可以提高性能。

     

使用ObjectContext,ObjectQuery和ObjectSet实例进行查询时   一旦设置了MergeOption,它就会记住   由它们组成的将继承父级的有效MergeOption   查询。使用DbContext时,可以通过调用   DbSet上的AsNoTracking()修改器。

简而言之,是的,通过使用AsNoTracking,您可以获得更好的性能,尤其是当您要加载大量数据行时,但是不要忘记它不会影响SQL生成的查询,只会增加.NET中的效果。

AsNoTracking vs Tracking

enter image description here

ps: 图表取自StaticVoid blog

答案 1 :(得分:1)

您需要使用编译查询(LINQ到实体)

请参阅enter link description here

还有一件事,如果您想要子数据,请设置 LazyLoding = true

默认在EntityFramework DBContext类中为LazyLoding = true

实体框架中的延迟加载

延迟加载会延迟相关数据的加载,直到您明确要求为止。这与渴望加载相反。 例如, Student 实体包含 StudentAddress 实体。在延迟加载中,上下文首先从数据库加载 Student 实体数据,然后在我们访问< strong> StudentAddress 属性,如下所示。

using (var ctx = new SchoolDBEntities())
{
    //Loading students only
    IList<Student> studList = ctx.Students.ToList<Student>();

    Student std = studList[0];

   //Loads Student address for particular Student only (seperate SQL query)
   StudentAddress add = std.StudentAddress;
}

上面显示的代码将导致两个SQL查询。首先,它将获取所有学生:

SELECT 
[Extent1].[StudentID] AS [StudentID], 
[Extent1].[StudentName] AS [StudentName], 
[Extent1].[StandardId] AS [StandardId]
FROM [dbo].[Student] AS [Extent1]

然后,当我们获得StudentAddress的引用时,它将发送以下查询:

    exec sp_executesql N'SELECT 
[Extent1].[StudentID] AS [StudentID], 
[Extent1].[Address1] AS [Address1], 
[Extent1].[Address2] AS [Address2], 
[Extent1].[City] AS [City], 
[Extent1].[State] AS [State]
FROM [dbo].[StudentAddress] AS [Extent1]
WHERE [Extent1].[StudentID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1

禁用延迟加载

我们可以为特定实体或上下文禁用延迟加载。要关闭特定属性的延迟加载,请勿使其变为虚拟。要关闭上下文中所有实体的延迟加载,请将其配置属性设置为false。

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Core.Objects;
using System.Linq;

public partial class SchoolDBEntities : DbContext
{
    public SchoolDBEntities(): base("name=SchoolDBEntities")
    {
        this.Configuration.LazyLoadingEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    }
}

延迟加载规则:

  • context.Configuration.ProxyCreationEnabled应该为true。

  • context.Configuration.LazyLoadingEnabled应该为true。

  • 导航属性应定义为公共虚拟属性。上下文
    如果该属性未定义为virtual,则不会进行延迟加载。