EF6中DbSet.Find方法为何每次都直接查询数据库?
问题分析与解决
你遇到的问题核心是EF6的Find方法缓存匹配失败,明明实体已加载到ObjectStateManager,却仍重复查询数据库,最可能的原因是主键类型不匹配:
关键问题点
你的TestRq实体主键定义为decimal类型:
[Key] public decimal RQ {get; set;}
但调用Find时传入的是整数类型的3:
testContext.TestRq.Find(3);
EF6在ObjectStateManager中查找实体时,会严格匹配主键的类型——缓存中的实体主键是decimal(3),而你传入的是int类型的3,类型不匹配导致缓存查找失败,每次都会触发数据库查询。
解决方法
将Find的参数改为decimal类型(在数字后加m标识):
using var testContext = new TestContext("Test"); // 用decimal类型的3m作为参数 var testRqFind = testContext.TestRq.Find(3m); Thread.Sleep(5000); // 同样传入decimal类型参数 testRqFind = testContext.TestRq.Find(3m);
修改后再次测试,SQL Profiler应该只会出现一次数据库查询,第二次Find会直接返回ObjectStateManager中的缓存实体。
额外排查点(如果上述方法无效)
- 检查是否意外关闭了实体跟踪:确保没有在
DbSet上调用AsNoTracking(),也没有修改testContext.Configuration.AutoDetectChangesEnabled = false(默认是开启状态) - 确认实体确实被上下文跟踪:可以在第一次
Find后,通过testContext.ChangeTracker.Entries<TestRq>()查看跟踪的实体列表,确认目标实体存在
内容的提问来源于stack exchange,提问作者Leandro Tiraboschi
相关产品推荐
相关产品推荐

