我目前正在学习实体框架,正在尝试做一个小型研究项目。它有效,但表现非常糟糕,我希望有人可以向我展示一些改进,我可以做些什么来加快速度。
有以下类:
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之后还有一些查询,我不希望从数据库中接收不包含所有给定过滤器的实体。有没有办法用逗号分隔的字符串或类似的东西来做呢?
非常感谢提示!
答案 0 :(得分:3)
这是因为EF使用Intersect
创建了一个怪异的查询。它以某种方式将列表filters
转换为SQL,并通过UNION
为列表中的每个元素执行单值SELECT
。这种情况在一次查询中会多次发生。
我经历过Intersect
,Except
以及有时候All
和Any
等语句通常更好地避免使用Contains
替换为解决方案,因为Contains
总是被翻译成IN
语句。在您的情况下将是
from filtent in query
where filtent.Tags.All(f => filters.Contains(f) )
select filtent
我确信这会产生一个更好的查询,也会表现得更好。在这种情况下,All
语句会转换为无害的NOT EXISTS
。