Linq查询使用ID返回结果过慢(EF Core)

3
我有以下的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个匹配项,所以这里没有太多事情要做。

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

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

SELECT *
FROM Address
WHERE ZipCode = '29130'

原因是有时L2S或实体框架不会发出优化的查询。执行路径并不总是很好。你的替代方案是创建一个存储过程,并使用实体框架调用它。如果需要完整的解决方案,请告诉我。 - Pratik Gaikwad
你是指在数据库中使用存储过程吗?不幸的是,我无法控制数据库,只有读取查询和添加存储过程不是一个选项。您有任何其他想法吗?也许我需要摆脱EF并使用常规的SQL连接? - user3587624
原因很简单,就是需要时间。每次调用EF函数时,都会创建SQL脚本并编译。因此,它总是需要时间。让我想想有没有其他替代方案。但与此同时,你可以尝试在这个函数中使用ADO。 - Pratik Gaikwad
ZipCode是nvarchar还是varchar类型? - Robert McKee
数据库将ZipCode定义为varchar。 - user3587624
2个回答

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();
     }
    }

1
在EntityFramework Core中,LazyLoading不是一个选项,因此我无法完全禁用它。 - user3587624
那么,使用 AsNoTracking() 会有什么改进吗? - Sampath
你是否正确使用了? 请参考这个链接: https://jessedotnet.com/2016/03/17/entity-framework-7-solve-you-large-dataset-performance-issues-with-asnotracking/ - Sampath
好的,请查看我上面的更新并让我知道现在 //禁用跟踪 - Sampath
1
我确实提高了一点性能,但并不是很多。看起来在当前的EF Core中没有太多可以做的,所以我会接受你的建议为有效:)。然而,我将实现自己的SQL连接类,并避免使用EF来执行这个特定的查询,因为性能对于这个特定的情况来说并不好。谢谢! - user3587624
显示剩余3条评论

0

我不知道你正在使用哪个版本的.Net和实体框架,但我在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();
     }            
}

目前我没有任何远程数据库进行测试,但是查询结果的延迟也取决于网络和获取的记录数。您可以尝试这个解决方案。


我尝试了这个选项,但是在ASP.NET Core上没有CompiledQuery类可用。 - user3587624

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接