EF6.2中使用InteractiveViews未显著提升首次查询性能的问题排查
让我们一步步梳理你的问题,先解决核心疑问,再排查性能提升不明显的原因:
1. InteractiveViews 对 Entity Framework 6.2 的支持情况
先给你吃个定心丸:InteractiveViews(即EntityFramework.InteractiveViews NuGet包)完全支持EF6.2。这个包的维护版本专门适配了EF6全系列版本,版本兼容不是你当前问题的核心原因。
2. 你的实现中存在的关键问题
性能提升不明显的根源在于代码里的几个逻辑错误,导致预生成视图的缓存根本没生效:
问题1:预生成视图的逻辑没有触发视图写入缓存
你的OneTimeSetUp方法里只是创建了DbContext并设置了缓存工厂,但没有触发EF的模型初始化和视图生成操作。InteractiveViews需要EF完成一次完整的模型构建(通常通过执行查询或手动初始化数据库),才能把生成的视图写入到EFCache.xml文件中。你当前的代码只是初始化了缓存工厂,没有让EF真正生成视图,所以缓存文件里没有有效内容。
看这段有问题的代码:
Start(() => { using (var ctx = new ThickDbContext(_connectionDictionary[1].ToString())) { InteractiveViews.SetViewCacheFactory( ctx, _veiwFactory ); } Debug.WriteLine($"Work with cache consumed: {_watch.ElapsedMilliseconds} ms."); });
这里只是创建了DbContext并绑定缓存工厂,但没有执行任何会触发模型构建的操作,自然不会生成视图缓存。
问题2:测试查询没有启用视图缓存
在QueryExecutionPerfomanceTest方法中,你新建了ThickDbContext但没有调用InteractiveViews.SetViewCacheFactory启用缓存。这次查询完全没有使用预生成的视图,还是在实时动态生成视图,这就是性能提升微乎其微的核心原因。
问题3:计时逻辑不准确
Setup里的计时包含了无意义的DbContext创建操作,没有覆盖视图生成的核心耗时;测试方法里的计时也没有区分DbContext初始化、视图生成、查询执行的不同阶段,导致数据参考性不强。
3. 修复后的实现建议
步骤1:正确预生成并写入视图缓存
修改Setup方法,确保触发模型初始化并将视图写入缓存:
[OneTimeSetUp] public void Setup() { _watch = new Stopwatch(); _connectionDictionary = new Dictionary<int, SqlConnectionStringBuilder>() { { 1, new SqlConnectionStringBuilder() { UserID = "UserId", Password = "Password", InitialCatalog = "MyDatabase", DataSource = @"MyDb", ConnectTimeout = 30, MinPoolSize = 0, MaxPoolSize = 100, MultipleActiveResultSets = true, } } }; _path = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\", "EFCache.xml")); _veiwFactory = new FileViewCacheFactory(_path); // 预生成视图并写入缓存:强制EF初始化模型,触发视图生成 _watch.Start(); using (var ctx = new ThickDbContext(_connectionDictionary[1].ToString())) { InteractiveViews.SetViewCacheFactory(ctx, _veiwFactory); // 强制初始化数据库模型,触发视图生成并写入缓存 ctx.Database.Initialize(force: true); // 或者执行任意简单查询,比如 ctx.RESOURCES.Any(); } _watch.Stop(); Debug.WriteLine($"预生成视图并写入缓存耗时: {_watch.ElapsedMilliseconds} ms."); }
运行这段代码后,检查EFCache.xml,应该能看到包含大量视图定义的XML内容,这才说明缓存生成成功。
步骤2:在测试查询中启用视图缓存
修改测试方法,确保使用预生成的视图缓存:
[Test] [TestCase(1)] public void QueryExecutionPerfomanceTest(int id) { // Arrange. var sqlConnection = _connectionDictionary[id].ToString(); // Act. _watch.Reset(); _watch.Start(); using (var dbContext = new ThickDbContext(sqlConnection)) { // 必须绑定缓存工厂,才能读取预生成的视图 InteractiveViews.SetViewCacheFactory(dbContext, _veiwFactory); var result = dbContext.RESOURCES.SingleOrDefault(r => r.RESOURCEID == id); _watch.Stop(); _info = new QueryDataDTO { Id = id, DurationTime = _watch.ElapsedMilliseconds, Source = typeof(RESOURCE).Name, }; // Assert. Debug.WriteLine($"id: {_info.Id}. Duration: {_info.DurationTime} ms."); } }
现在测试时会直接读取缓存的视图,跳过动态生成步骤,对于482个实体的大型DbContext,性能提升应该能达到50%以上。
步骤3:额外优化建议
- 把缓存文件路径调整到项目输出目录,避免路径解析错误导致缓存无法读取。
- 多次运行测试取平均值,避免单次运行的波动影响结果。
- 确保
ThickDbContext的构造函数没有额外的初始化逻辑,避免干扰计时准确性。
内容的提问来源于stack exchange,提问作者AllmanTool

