【发布时间】:2023-04-05 01:52:02
【问题描述】:
我正在使用 Entity Framework 6 访问数据库。
以下两种方法有性能差异吗?
public IEnumerable<TEntity> GetAll()
{
using (var context = new DbContext())
return context.Set<TEntity>().ToList();
}
和
public IEnumerable<TEntity> GetAll()
{
using (var context = new DbContext())
return context.Set<TEntity>().Where(e => true).ToList();
}
我问是因为我想使用条件谓词。如下所示。
public IEnumerable<TEntity> GetAll(TKey fKey)
{
using (var context = new DbContext())
return context.Set<TEntity>()
.Where(e => fKey != null ? e.fKey == fKey : true).ToList();
}
fKey 是外键。
更新:由于许多 cmets 都关注我的最后一个示例,我同意这是一个不好的用例,我将解释我为什么要问。
所以我有如下所示的存储库方法。
public class EntityRepository
{
public IEnumerable<Entity> GetAll(Expression<Func<Entity, bool>> predicate)
{
using (var context = new DbContext())
return context.Set<Entity>.Where(predicate).ToList();
}
}
我正在使用这种方法形成 Web API 控制器的操作方法。类似于以下内容。
public IHttpActionResult GetEntities(string param1, string param2, string param3)
{
Expression<Func<Entity, bool>> predicate = e =>
(param1 != null ? e.field1 == param1 : true)
&& (param2 != null ? e.field2 == param2 : true)
&& (param3 != null ? e.field3 == param3 : true);
var entities = EntityRepository.GetAll(predicate);
return Ok(entities);
}
所以在这里我从 URI 中获取一些查询参数,并根据它们创建谓词。其中一些参数可以是null,在这种情况下我不想过滤这些参数。但我不想为是否为nulls 的所有参数组合创建不同的谓词。
我知道我可以读取整个数据集并在之后逐个过滤,但这会占用大量内存来处理大数据集。
所以只是为了澄清我的问题:这是正确的方法吗?如果所有 3 个参数都是 null(在这种情况下将返回整个集合),此方法是否会导致任何性能挫折?
【问题讨论】:
-
如果您知道
fkey为空,为什么要使用它?只是不要将它添加到表达式中。至于性能,取决于SQL查询和生成的执行计划。前两个查询可能会创建相同的 SQL 或等效的执行计划。第三个不会,它会创建一个包罗万象的查询,这通常会导致错误的执行计划 -
看起来您正在尝试在更高级别的 ORM(如实体框架)之上实现通用存储库 anti 模式。检查
DbSet<T>。您自己的课程提供了 DbSet 没有的什么?如果你的类只是一个薄包装器,为什么你要使用它? 实体没有外键,它们有关系和导航属性。如果您的“存储库”不理解这一点,如果它因为“通用”而无法利用关系,那么它会造成伤害而没有真正的好处。它降低抽象级别低于 EF 或任何其他 ORM 提供的抽象级别 -
感谢您的回答!我可以看到我的错误示例引起了一些混乱,所以请检查我的更新!
-
没有混淆。包罗万象的查询很糟糕。是的,空值会导致性能问题,因为它们会导致错误的执行计划被缓存和重用。 Jesse 表明,在使用 LINQ 时,您一开始就不需要它们。 This article explains 为什么包罗万象的查询不好
标签: c# database performance entity-framework entity-framework-6