Entity Framework,在存储库而不是服务层查询是否有任何性能改进?
Entity Framework, Is there any performance improvement on querying at repository instead at service layer?
Entity Framework,在存储库而不是服务层查询是否有任何性能改进?
Entity Framework有没有类似SQL的性能提升引擎?它是否知道所有接下来的 3 个伪代码只是 1 个 DB 调用,或者它首先真正获得一些 FilteredContidionA,然后应用第二个条件?
CASE A)
clients.Where( someFilterConditionA);
clients.Where( someFilterConditionB);
return clients;
CASE B)
clients.Where( someFilterConditionA).Where( someFilterConditionB);
return clients;
CASE C)
clients.Where( someFilterConditionA AND someFilterConditionB);
return clients;
EF 确实有优化,您的 3 个案例之间应该没有任何区别。您可以轻松地 运行 一个 SQL 探查器来检查 EF 发送到数据库的任何查询。
就执行而言:成本是在执行时发生的,无论它是在何处触发的。这通常是调用 .ToList / .First / .Any / .Count 等的地方。我看到人们犯的最大性能错误如下所示:
var results = dbContext.ParentEntities.Where(x=> x.SomeCriteria == true).ToList();
// later down the call stack...
var results = repostitory.GetParents(criteria);
if (results.Count > 0)
// never actually use results, or do something like results.FirstOrDefault(), etc.
还有不恰当的延迟加载或急切加载的罪过,return加载整个实体图,其中实际只使用了几个字段。
我遵循的模式是使用延迟执行/w 存储库模式。这意味着我的存储库,除了少数例外,总是 return IQueryable<TEntity>
。即使是只需要 1 个实体的方法。 (即 GetById())存储库管理低级规则,例如软删除系统的授权和 IsActive 之类的东西,以及历史数据的时间考虑因素,但我让业务逻辑根据附加条件根据需要进一步细化查询,定义将选择哪些字段,以及在执行延迟查询之前如何检索数据。
这种方法的好处是我的存储库可以作为我的单元测试的一个简单的截止点,我只需要 return 从模拟存储库中备份实体列表之类的东西来练习我的业务逻辑。从维护的角度来看,我的存储库非常薄。不需要针对不同的标准或预期的 return 类型使用大量类似的方法,也不需要将模糊的表达式树等传递到函数中以进行中继过滤。从性能的角度来看,让业务逻辑控制数据的过滤和使用方式,这为我提供了很大的灵活性,并有助于确保轻松优化查询。我的业务逻辑可以:
- Select仅实体中的字段和它需要的相关实体。
- Return 只有它需要的行。 (.FirstOrDefault, .Skip.Take, 等等)
- 处理其他业务逻辑决策。 (.Any、.Count 等)
所有这些都没有触及存储库定义。存储库成为一个精简服务 class 以方便测试。
反对这种模式的论点是,拥有一个带有显式和静态查询的存储库可以为调整索引提供一个更慎重的目标。我的反对意见是,索引调整应该基于系统的使用方式,而不是应该尝试尽早优化的东西。静态存储库和查询意味着您需要维护大量额外代码,并且在许多情况下 运行 宁次优查询。 (即 returning IEnumerable<Entity>
)很多方法本质上做相同的事情 returning 不同的数据结构,或者更少的方法 returning 整个实体,其中只有实际上需要的细节很少。 IMO:构建系统,使用系统,调整系统。
Entity Framework,在存储库而不是服务层查询是否有任何性能改进?
Entity Framework有没有类似SQL的性能提升引擎?它是否知道所有接下来的 3 个伪代码只是 1 个 DB 调用,或者它首先真正获得一些 FilteredContidionA,然后应用第二个条件?
CASE A)
clients.Where( someFilterConditionA);
clients.Where( someFilterConditionB);
return clients;
CASE B)
clients.Where( someFilterConditionA).Where( someFilterConditionB);
return clients;
CASE C)
clients.Where( someFilterConditionA AND someFilterConditionB);
return clients;
EF 确实有优化,您的 3 个案例之间应该没有任何区别。您可以轻松地 运行 一个 SQL 探查器来检查 EF 发送到数据库的任何查询。
就执行而言:成本是在执行时发生的,无论它是在何处触发的。这通常是调用 .ToList / .First / .Any / .Count 等的地方。我看到人们犯的最大性能错误如下所示:
var results = dbContext.ParentEntities.Where(x=> x.SomeCriteria == true).ToList();
// later down the call stack...
var results = repostitory.GetParents(criteria);
if (results.Count > 0)
// never actually use results, or do something like results.FirstOrDefault(), etc.
还有不恰当的延迟加载或急切加载的罪过,return加载整个实体图,其中实际只使用了几个字段。
我遵循的模式是使用延迟执行/w 存储库模式。这意味着我的存储库,除了少数例外,总是 return IQueryable<TEntity>
。即使是只需要 1 个实体的方法。 (即 GetById())存储库管理低级规则,例如软删除系统的授权和 IsActive 之类的东西,以及历史数据的时间考虑因素,但我让业务逻辑根据附加条件根据需要进一步细化查询,定义将选择哪些字段,以及在执行延迟查询之前如何检索数据。
这种方法的好处是我的存储库可以作为我的单元测试的一个简单的截止点,我只需要 return 从模拟存储库中备份实体列表之类的东西来练习我的业务逻辑。从维护的角度来看,我的存储库非常薄。不需要针对不同的标准或预期的 return 类型使用大量类似的方法,也不需要将模糊的表达式树等传递到函数中以进行中继过滤。从性能的角度来看,让业务逻辑控制数据的过滤和使用方式,这为我提供了很大的灵活性,并有助于确保轻松优化查询。我的业务逻辑可以:
- Select仅实体中的字段和它需要的相关实体。
- Return 只有它需要的行。 (.FirstOrDefault, .Skip.Take, 等等)
- 处理其他业务逻辑决策。 (.Any、.Count 等)
所有这些都没有触及存储库定义。存储库成为一个精简服务 class 以方便测试。
反对这种模式的论点是,拥有一个带有显式和静态查询的存储库可以为调整索引提供一个更慎重的目标。我的反对意见是,索引调整应该基于系统的使用方式,而不是应该尝试尽早优化的东西。静态存储库和查询意味着您需要维护大量额外代码,并且在许多情况下 运行 宁次优查询。 (即 returning IEnumerable<Entity>
)很多方法本质上做相同的事情 returning 不同的数据结构,或者更少的方法 returning 整个实体,其中只有实际上需要的细节很少。 IMO:构建系统,使用系统,调整系统。