【问题标题】:Linq query using ID returns result to slow (EF Core)使用 ID 的 Linq 查询将结果返回慢(EF Core)
【发布时间】:2017-01-18 04:18:29
【问题描述】:

我有以下 linq 查询

internal List<ZipCodeInfo> GetInfoFromZipCode(string zipCode)
{
    using (DbContext context = new DbContext())
    {
        IQueryable<ZipCodeInfo> results;

        results = (from a in context.Address
                    where a.ZipCode.Equals(zipCode)
                    select new ZipCodeInfo
                    {
                        Field1 = a.Field1,
                        Field2 = a.Field2,
                        Field3 = a.Field3
                    });

        return results.ToList();
    }
}

但查询本身大约需要 5-6 秒才能完成。我已经在 SQL 上执行了对应的查询,几乎不需要完成任何事情。为什么要花这么长时间?最后的查询只返回 4 个匹配项,所以这里没有太多可做的..

此查询是 Controller 类的一部分,我正在使用 ASP.NET Core 和 EntityFramework Core。

SQL 查询看起来像这样,顺便说一句。

SELECT *
FROM Address
WHERE ZipCode = '29130'

【问题讨论】:

  • 原因是有时 L2S 或实体框架不会发出优化查询。执行路径并不总是很好。您的替代方法是创建一个存储过程并使用实体框架调用它。如果您需要完整的解决方案,请告诉我。
  • 您的意思是数据库中的存储过程?不幸的是,我无法控制数据库,只能读取运行查询的权限,并且不能选择添加存储过程。知道是否有其他方法吗?也许我需要摆脱 EF 并使用常规 SQL 连接?
  • 原因很简单,因为它需要时间。每次调用函数 EF 都会创建 SQL 脚本并进行编译。所以总是需要时间。让我想一个替代方案。但与此同时,你能不能只用 ADO 来实现这个功能?
  • ZipCode 是 nvarchar 还是 varchar?
  • 数据库已将 ZipCode 定义为 varchar

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


【解决方案1】:

您可以重写上面的查询,如下所示。请立即告诉我们性能。

 internal List<ZipCodeInfo> GetInfoFromZipCode(string zipCode)
    {
        using (DbContext context = new DbContext())
        {
           //disabled tracking
           context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

            IQueryable<ZipCodeInfo> results;

            results = (from a in context.Address
                        where a.ZipCode.Equals(zipCode)
                        select new ZipCodeInfo
                        {
                            Field1 = a.Field1,
                            Field2 = a.Field2,
                            Field3 = a.Field3
                        });

            return results.ToList();
     }
    }

【讨论】:

  • 延迟加载不是 EntityFramework Core 的选项,所以我根本无法禁用它
  • 是的,那么 AsNoTracking() 呢?有什么改善吗?
  • AsNoTracking() 在 EF Core 上也不是一个选项 :(
  • 什么?你用对了吗?请看这个:jessedotnet.com/2016/03/17/…
  • 我确实提高了一点性能,但没有那么多。在这一点上,目前的 EF Core 似乎没有太多可做的事情,所以我会接受你的建议有效:)。但是,我将实现我自己的 SQL Connection 类并执行此特定查询以避免 EF,因为对于这种特定情况,性能不是很好。谢谢!
【解决方案2】:

我不知道你使用的是什么版本的 .Net 和实体框架,但我发现了一篇有趣的文章 here on MSDN。你可以通过它。但是代码可以如下使用:

static readonly Func<DbEntities, IQueryable<ZipCodeInfo>> s_compiledQuery2 = 
CompiledQuery.Compile<DbEntities, IQueryable<ZipCodeInfo>>(
(ctx, total) => from a in context.Address
                where a != null and a != "" 
                a.ZipCode.ToUpper().Equals(zipCode.ToUpper())
                select new ZipCodeInfo
                {
                    Field1 = a.Field1,
                    Field2 = a.Field2,
                    Field3 = a.Field3
                });

internal List<ZipCodeInfo> GetInfoFromZipCode(string zipCode)
{            
     using (DbEntities context = new DbEntities())
     {
          IQueryable<ZipCodeInfo> zipCodes = s_compiledQuery2.Invoke(context, zipCode);
          return zipCodes.ToList();
     }            
}

此时我没有任何远程数据库要测试,但再次延迟获取此类查询的结果也将取决于 N\W 和正在获取的记录数。你可以试试这个解决方案。

【讨论】:

  • 我试过这个选项,但 CompiledQuery 类在 ASP.NET Core 上不可用
猜你喜欢
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2020-03-29
  • 2016-10-10
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多