C# IQueryable<;T>;列出<;T>;性能问题

C# IQueryable<;T>;列出<;T>;性能问题,c#,iqueryable,generic-list,C#,Iqueryable,Generic List,我有下面的代码可以正常工作,但在性能方面有一些问题。通过调试,我可以看到,当代码出现在下面这一行时,需要10秒的时间才能完成 List<T> queryableListdResult = queryableInitialResult.ToList(); List queryableListdResult=queryableInitialResult.ToList(); 基本上,下面的代码从数据库中的150000条记录中获取大约15000条文章 有人能建议一个更好的方法吗?谢谢 我

我有下面的代码可以正常工作,但在性能方面有一些问题。通过调试,我可以看到,当代码出现在下面这一行时,需要10秒的时间才能完成

List<T> queryableListdResult = queryableInitialResult.ToList();
List queryableListdResult=queryableInitialResult.ToList();
基本上,下面的代码从数据库中的150000条记录中获取大约15000条文章

有人能建议一个更好的方法吗?谢谢

我的代码:

        public static IQueryable<T> CategoryFilter<T>(IQueryable<T> queryable, int categoryFilterCount, RenderingContext rc, bool CategoryOR, string categoriesforQuery) where T : AbstractResult
        {


        if (!string.IsNullOrEmpty(categoriesforQuery))
        {
            string[] categoriesDefined = categoriesforQuery.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            List<T> listInitialResult = new List<T>();


            foreach (string TaxonomyID in categoriesDefined) //e.g. entertainment, business
            {
                string categoryToCompare = TaxonomyID.ToString().Replace("{", "").Replace("}", "");
                queryable = queryable.Where(i => i.alltags.Contains(categoryToCompare));

                List<T> queryableListdResult = queryable.ToList();


                listInitialResult.AddRange(queryableListdResult);
            }
            if (CategoryOR)
            {
                return listInitialResult.AsQueryable();
            }
            else
            {
                List<T> queryableFinalResult = (listInitialResult.GroupBy(x => x._Group).Where(g => g.Count() >= categoryFilterCount)
                .Select(g => g.FirstOrDefault())).ToList();
                return queryableFinalResult.AsQueryable();
            }

        }
        else
        {
            return queryable;
        }
    }
public static IQueryable CategoryFilter(IQueryable queryable,int categoryFilterCount,RenderingContext rc,bool CategoryOR,string categoriesforQuery),其中T:AbstractResult
{
如果(!string.IsNullOrEmpty(categoriesforQuery))
{
string[]categoriesDefined=categoriesforQuery.Split(新字符[]{'|'},StringSplitOptions.RemoveEmptyEntries);
List listInitialResult=新列表();
foreach(categoriesDefined中的字符串TaxonomyID)//例如娱乐、商业
{
string categoryToCompare=TaxonomyID.ToString().Replace(“{”,“”)。Replace(“}”,“”);
queryable=queryable.Where(i=>i.alltags.Contains(categoryToCompare));
List queryableListdResult=queryable.ToList();
listInitialResult.AddRange(queryableListdResult);
}
if(分类商)
{
返回listInitialResult.AsQueryable();
}
其他的
{
List queryableFinalResult=(listInitialResult.GroupBy(x=>x.\u Group)。其中(g=>g.Count()>=categoryFilterCount)
.Select(g=>g.FirstOrDefault()).ToList();
返回queryableFinalResult.AsQueryable();
}
}
其他的
{
返回可查询;
}
}

试试这个。我把你的代码并行化了

public static IQueryable<T> CategoryFilter<T>(IQueryable<T> queryable1, int categoryFilterCount, RenderingContext rc, bool CategoryOR, string categoriesforQuery) where T : AbstractResult
    {
        if (!string.IsNullOrEmpty(categoriesforQuery))
        {
            string[] categoriesDefined = categoriesforQuery.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            ConcurrentBag<T> listInitialResult = new ConcurrentBag<T>();

            Parallel.ForEach(categoriesDefined, (TaxonomyID) =>
            {
                string categoryToCompare = TaxonomyID.ToString().Replace("{", "").Replace("}", "");
                var queryable = queryable.Where(i => i.alltags.Contains(categoryToCompare));

                List<T> queryableListdResult = queryable.ToList();


                for (int i = 0; i < queryableListdResult.Count; i++)
                {
                    listInitialResult.Add(queryableListdResult[i]);
                }
            });

            if (CategoryOR)
            {
                return listInitialResult.AsQueryable();
            }
            else
            {
                List<T> queryableFinalResult = (listInitialResult.GroupBy(x => x._Group).Where(g => g.Count() >= categoryFilterCount)
                .Select(g => g.FirstOrDefault())).ToList();
                return queryableFinalResult.AsQueryable();
            }

        }
        else
        {
            return queryable;
        }
    }
public static IQueryable CategoryFilter(IQueryable queryable1,int categoryFilterCount,RenderingContext rc,bool CategoryOR,string categoriesforQuery),其中T:AbstractResult
{
如果(!string.IsNullOrEmpty(categoriesforQuery))
{
string[]categoriesDefined=categoriesforQuery.Split(新字符[]{'|'},StringSplitOptions.RemoveEmptyEntries);
ConcurrentBag listInitialResult=新ConcurrentBag();
Parallel.ForEach(categoriesDefined,(TaxonomyID)=>
{
string categoryToCompare=TaxonomyID.ToString().Replace(“{”,“”)。Replace(“}”,“”);
var queryable=queryable.Where(i=>i.alltags.Contains(categoryToCompare));
List queryableListdResult=queryable.ToList();
for(int i=0;ix.\u Group)。其中(g=>g.Count()>=categoryFilterCount)
.Select(g=>g.FirstOrDefault()).ToList();
返回queryableFinalResult.AsQueryable();
}
}
其他的
{
返回可查询;
}
}

另外,我使用了一个并发包,我相信这是一个无锁的问题。希望这有帮助

除了装载卡车数据。 在处理这一问题时,有一些技巧可以最大化EF上下文。 例如
Context.Configuration.AutoDetectChangesEnabled=false

您的代码片段表明toList()可能会在每次迭代中执行。 你可能想找到一种不同的方法来获得


List queryableListdResult=queryableInitialResult.ToList() 

请考虑查询的数据量。假设每篇文章只有1kB的数据。您正在删除15k个实体,但仍在尝试从数据库中获取15MB的数据。假设一个10Mb/s的链路10秒在数据传输速率方面几乎是正确的

我建议您要么投影查询以避免提取不必要的数据,要么升级数据链接

但是,如果您需要的是代码更具响应性,那么实际上可以使用流式
IEnumerable
。您只需使用
DbSet.AsStreaming()
方法。这会将数据传输成本分摊到
IEnumerator.Next()
的每个调用中。但是我警告您,数据传输本身将花费更长的时间,并且您将在传输的整个生命周期中保持datareader锁


把你的问题读得更透彻。您实际需要的是
IQueryable.Concat
。有了它,您可以在每个IQueryable上过滤您想要的所有内容,然后将它们合并在一起,最后是
.ToList()
它。

推荐的诊断工具。运行Sql事件探查器以发现您的调用生成的实际Sql。您需要所有这些记录,还是可以在数据库中筛选出一些记录?似乎要返回的数据太多了。我知道你已经在筛选了,但15k记录仍然是一个很好的选择lot@SCB不,我不需要所有这些记录,这只是筛选列表的第一步。然后我将继续应用筛选器以减少记录数,而不是调用iQueryTable上的ToList,这将导致对您的数据存储执行查询。@SCB很好,但我在聚合多个iQueryTables时遇到了问题。因此,我将其转换为List,然后执行了一个“AddRange”…您是否对照原始代码检查了它,以查看性能是否得到了改进?Linq中没有太多开销(Linq基本上是
for
循环和
yield
语句),但有一些开销。任何显著的加速都是由于。您必须将当前环路的状态存储在