Linq to Entities中Any方法始终返回true问题排查求助
首先,我一眼就发现你的代码逻辑写反了,这大概率是让你觉得Any()方法“异常”的核心原因!
1. 逻辑反转的关键问题
看你这段代码:
if (db.Items.Any(x => x.GivenId == newGivenId && x.Id != item.Id && x.TipId == item.TipId)) { //newGivenId要么不同,要么属于当前Item } else { //同一Tip下已有Item使用该newGivenId }
Any()返回true的实际含义是:存在其他Item(和当前Item ID不同)属于同一个Tip,并且GivenId和newGivenId重复——这正是你要拦截的“重复冲突”场景,但你现在把提示重复的逻辑放在了else分支,允许保存的逻辑放在了if分支,完全搞反了!
正确的逻辑应该是这样:
if (db.Items.Any(x => x.GivenId == newGivenId && x.Id != item.Id && x.TipId == item.TipId)) { // 同一Tip下已有Item使用该newGivenId,拒绝保存 } else { // newGivenId可用,执行编辑保存逻辑 }
2. NULL值比较的SQL转换坑
从你贴的生成SQL来看,三个参数@p__linq__0、@p__linq__1、@p__linq__2都被设为NULL。item.Id是int非可空类型,不可能为NULL,所以问题出在newGivenId或item.TipId为NULL的场景。
在C# Linq里,null == null是true,但SQL里NULL = NULL的结果是UNKNOWN,不会被判定为匹配。如果你的newGivenId或item.TipId是NULL,EF生成的SQL条件会和Linq语义不一致,导致Any()返回不符合预期的结果。
如果你的EF版本较旧,建议显式处理NULL比较:
db.Items.Any(x => (x.GivenId == newGivenId || (x.GivenId == null && newGivenId == null)) && x.Id != item.Id && (x.TipId == item.TipId || (x.TipId == null && item.TipId == null)) )
新版本EF会自动处理可空类型的NULL匹配,但显式写出来能避免歧义。
3. 调试小技巧
你提到FirstOrDefault()返回NULL符合预期,说明当前没有重复的记录,这时候Any()应该返回false。如果实际运行时Any()的结果和预期不符,建议调试时输出newGivenId、item.Id、item.TipId的具体值,同时核对SQL执行时的参数值,就能快速定位问题。
内容的提问来源于stack exchange,提问作者Ashkan Mobayen Khiabani

