我有两种根据Id查找实体的方法。第一个使用IQueryable对象,通过一个λ表达式根据Id查找对象,另一个使用内置的实体框架DbSet.Find()方法。我在Visual Studio中编写了几个单元测试,为这两种方法创建速度基准,以确定哪种方法更好。
有趣的是,我编写的方法比Find中内置的实体框架获得了更好的结果。有人知道为什么吗?
以下是Entity Framework方法的代码:
public virtual T Find<T>(int id)
{
return dbContext.Set<T>().Find(id);
}下面是我的方法的代码:
public virtual T FindById<T>(int id)
{
return dbContext.Set<T>().Where(x => x.IsActive).AsQueryable().FirstOrDefault(x => x.Id == id);
}下面是从数据库中选择几条记录所需的时间:

下面是我的测试类:
[TestClass]
public class EntityBenchmarks
{
EdiDataStore target;
[TestInitialize]
public void Start()
{
target = new EdiDataStore();
}
[TestCleanup]
public void Cleanup()
{
target.Dispose();
}
//this method is only here because i want to make sure that the
//database context is loaded into memory so that we can compare
//Find and FindById on an even scale. Without this method, the first
//time benchmark that runs is hit with the overhead of loading the model.
[TestMethod]
public void Control()
{
var entities = target.GetAgencies();
}
[TestMethod]
public void FindBenchmark()
{
bool isSuccess = true;
for (int i = 9177; i <= 9187; i++)
{
var entity = target.Find<Spot>(i);
isSuccess = isSuccess && entity != null;
}
Assert.IsTrue(isSuccess);
}
[TestMethod]
public void FindByIdBenchmark()
{
bool isSuccess = true;
for (int i = 9177; i <= 9187; i++)
{
var entity = target.FindById<Spot>(i);
isSuccess = isSuccess && entity != null;
}
Assert.IsTrue(isSuccess);
}
}发布于 2016-02-19 05:11:41
在不知道如何设置测试的情况下,甚至不可能尝试回答问题。会不会是FindBenchmark先运行,并且时间包含了引导EF的开销?EF在第一个查询上做了一些相当繁重的工作,这些查询与实际查询无关,但与延迟初始化有关,因此您不能真的将第一个查询与随后的查询进行比较。另一方面,Find首先在EF跟踪的实体中查找实体,而FindById将始终访问数据库-同样,如果您使用相同的上下文并切换顺序,结果可能完全不同,因为FindById将带来实体,而Find将不会访问数据库。
发布于 2016-02-19 05:50:45
性能测试有几处地方出了问题。
例如: dbContext.Set().Find(id)将产生类似如下的结果:
SELECT * FROM Foo WHERE FooID = 123
另一方面,dbContext.Set().Where(f => f.IsActive).FirstOrDefault(f => f.FooID == id)将生成如下内容:
SELECT * FROM FooID FooID= 123和IsActive =1
这本身可能会产生截然不同的结果,这取决于SQL使用什么索引以及SQL Server决定构建什么样的执行计划。如果你想比较不同的苹果,你应该比较:
dbContext.Set().Find(123);
与
dbContext.Set().Single(f => f.FooID == 123)
如果要显式测试检索相同数据的不同方法的性能,则需要确保这些方法执行完全相同的操作。确保这一点的最佳方法是运行SQL事件探查器,并确保生成的底层SQL是相同的。否则,您正在测试的就是SQL Server是否可以生成两个不同的数据库查询,这两个查询的执行时间或多或少都不同,这是没有意义的。
此外,不要对查询调用无关的扩展方法。在这种情况下,AsQueryable是无害的,但是调用错误的扩展方法也可以实现结果集,将每个实体重新放回内存中,并对内存中的集合运行另一个查询。这也会对性能产生巨大的影响。
https://stackoverflow.com/questions/35492367
复制相似问题