包含实体框架中的所有查询时性能不佳

时间:2014-12-12 13:11:25

标签: sql linq entity-framework

我目前正在学习实体框架,正在尝试做一个小型研究项目。它有效,但表现非常糟糕,我希望有人可以向我展示一些改进,我可以做些什么来加快速度。

有以下类:

public class Tag
{
    public string Id{get;set}
    public string Tag{
    get{ return Id;}
}

public class AnEntity
{
    [...]
    public virtual ICollection<Tag> Tags{ get; set;}
}

我以这种方式查询数据库:

var query = from entity in db.AnEntities
    where [...]
    select new {
        [...]
        Tags = entity.Tags.Select(tag => tag.Id).ToList()
    }

如果我现在使用await query.ToListAsync()执行查询,那么性能非常合理。 但是,如果我想过滤搜索并仅返回包含所有给定标签集的AnEntities,那么性能非常糟糕。我做&#34;包含所有查询&#34;这样:

var filters = new List<string>(){"Filter1", "Filter2"};
from filtent in query
    where filters.Intersect(filtent.Tags).Count() == filters.Count
    select filtent;

是否有一种更聪明的方法可以做到这一点&#39;包含所有&#39;查询?

编辑:我还考虑过用逗号分隔的字符串替换标签,但我不确定如何运行“包含全部”字符串。直接在数据库上查询。这很重要,因为在filterquery之后还有一些查询,我不希望从数据库中接收不包含所有给定过滤器的实体。有没有办法用逗号分隔的字符串或类似的东西来做呢?

非常感谢提示!

1 个答案:

答案 0 :(得分:3)

这是因为EF使用Intersect创建了一个怪异的查询。它以某种方式将列表filters转换为SQL,并通过UNION为列表中的每个元素执行单值SELECT。这种情况在一次查询中会多次发生。

我经历过IntersectExcept以及有时候AllAny等语句通常更好地避免使用Contains替换为解决方案,因为Contains总是被翻译成IN语句。在您的情况下将是

from filtent in query
where filtent.Tags.All(f => filters.Contains(f) )
select filtent

我确信这会产生一个更好的查询,也会表现得更好。在这种情况下,All语句会转换为无害的NOT EXISTS