【问题标题】:Performance of Linq query is very slowLinq 查询的性能很慢
【发布时间】:2020-04-15 22:55:40
【问题描述】:

我有 700 条记录,它们有不同的列,类型为字符串,我想使用此代码选择所有记录:

public virtual object GetAll()
{
    var AllList = unitOfWork.Repository<STUser>().GetAll().ToList();

    return (from STUser in AllList
            select new
            {
                STUser.ID,
                FullName = STUser.HRPerson.LastName,
                STUser.USR,
                STUser.Active,
                STUser.TryCount,
                STUser.Description           
            }).OrderByDescending(i => i.ID).ToList();
}

不过,unitl Fill "var AllList" 很好但是当Linq 查询执行时很慢。 我删除了FullName = STUser.HRPerson.LastName, 行,它执行得非常快。 Join 子句减慢了速度。

我为列表中的每一行运行 SQL 分析器,看起来它执行了 700 次查询。 查询是

exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[LastName] AS [LastName], 
[Extent1].[EnFullName] AS [EnFullName], 
[Extent1].[FatherName] AS [FatherName], 
[Extent1].[GenderID] AS [GenderID], 
[Extent1].[NationalCode] AS [NationalCode], 
[Extent1].[IdentityNumber] AS [IdentityNumber], 
[Extent1].[BirthCityID] AS [BirthCityID], 
[Extent1].[BirthDate] AS [BirthDate], 
[Extent1].[VeteranID] AS [VeteranID], 
[Extent1].[PersonPic] AS [PersonPic], 
[Extent1].[Active] AS [Active], 
[Extent1].[Description] AS [Description], 
[Extent1].[DateTimes] AS [DateTimes]
FROM [dbo].[HRPerson] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1502

请帮帮我。

【问题讨论】:

  • 这就是延迟加载的效果,您可能想要 Eager - 请参阅 docs.microsoft.com/en-us/ef/ef6/querying/related-data
  • @HansKesting when 执行查询完全不会影响查询的duration。但是,一次又一次地执行相同的查询是另一个问题,确实会影响性能。
  • 不使用.ToList() 上的var AllList = unitOfWork.Repository&lt;STUser&gt;().GetAll().ToList(); 怎么办
  • 您是否对此进行了分析,例如使用 DotTrace?您的性能瓶颈到底在哪里?您可能在这里查看错误的代码。从你发布的内容来看,我们在这里没什么可做的。
  • 尝试将 .GetAll().ToList() 更改为 .GetAll().Include(u =&gt; u.HRPerson).ToList(),以在获取所有用户的同时尝试并急切地获取该 hrperson,而不是作为单独的查询(我假设正在发生)

标签: c# linq


【解决方案1】:

我在 repo 中使用 IQueryable 并添加 Include(u => u.HRPerson) 就可以了

var AllList = unitOfWork.Repository<STUser>().GetAll().Include(u => u.HRPerson).ToList();

感谢@HansKesting 的帮助

【讨论】:

    【解决方案2】:

    我想分享一个想法:(我不熟悉那个平台)

    这个呢:

    public virtual IEnumerable<YourDataObject> GetAll()
    {
        var result = from STUser in unitOfWork.Repository<STUser>().GetAll() // << what is GetAll()??
                     orderby STUser.ID
                     select new YourDataObject // <-- you should create a data holder class for it
                     {
                        STUser.ID,
                        FullName = STUser.HRPerson.LastName,
                        STUser.USR,
                        STUser.Active,
                        STUser.TryCount,
                        STUser.Description
                     });
    
        return result;
    }
    

    通过在创建数据持有者类之前进行排序,您可能在数据库端使用优化。

    【讨论】:

    • GetAll() 是调用 IEnumerable models = dbSetGlobalERP.ToList(); 的方法使用您的代码但不受影响。帮我解决很大的问题。范你远程我,看看我的代码?
    • 你所寻求的是,IQueryable&lt;&gt;,所以订购可以在服务器端完成。 unitOfWork.Repository&lt;STUser&gt;() 返回什么?
    • 我使用 IQueryable 但不受影响。返回{ ID = 960,全名=“约翰史密斯- 2294089499”,USR =“h.ranjbar”,Active = true,TryCount = 0,描述=“”,DateTimes =“1398/10/28 15:12”}
    • 可以尝试 Jeroen 的 sn-p 代码,但没有 ".GetAll()" ?由于 unitOfWork.Repository() 返回 IQueryable,我们还不想使用 .GetAll() 对其进行评估。
    • @Markuzy 我测试它但不受影响
    【解决方案3】:

    您可以尝试在查询中使用 .AsNoTracking()。

    来自 Microsoft 文档 -

    当结果用于只读方案时,没有跟踪查询是有用的。它们执行速度更快,因为无需设置更改跟踪信息。如果您不需要更新从数据库中检索到的实体,则应使用无跟踪查询。您可以将单个查询交换为不跟踪。

    更多信息在这里 - https://docs.microsoft.com/en-us/ef/core/querying/tracking

    【讨论】:

    • 我使用 AsNoTracking() 但这没有影响
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2012-03-27
    相关资源
    最近更新 更多