Entity Framework Core中Join查询结果异常问题
这事儿确实有点费解——你在SQL Server里执行的Inner Join查询完全没结果(这是你预期的),但用EF Core写的逻辑类似的查询,传一样的参数却返回了一行不该出现的数据。咱们一步步来捋清楚问题出在哪。
先对比下两边的查询逻辑
数据库中执行的SQL(无结果,符合预期)
select * from device d inner join store s on s.Id = d.StoreId inner join category c on c.Id = d.CategoryId where s.StoreName like '%dsfd%' and c.CategoryName like '%asdasdasd1%'
EF Core中的C#查询(返回了不符合条件的行)
var serachresult = (from devices in _deviceRepository.GetAll() join stores in _storeRepository.GetAll() on devices.StoreId equals stores.Id join categories in _categoryRepository.GetAll() on devices.CategoryId equals categories.Id where (!string.IsNullOrWhiteSpace(searchInput.StoreName) ? stores.StoreName.Contains(searchInput.StoreName) : true) && (!string.IsNullOrWhiteSpace(searchInput.CategoryName) ? categories.CategoryName.Contains(searchInput.CategoryName) : true) select new DeviceDetailsDto { Id = devices.Id, DeviceName = devices.DeviceName, DeviceDesc = devices.DeviceDesc, DeviceCode = devices.DeviceCode, StoreId = devices.StoreId, CategoryId = devices.CategoryId, CategoryName = categories.CategoryName, StoreName = stores.StoreName });
你返回的精简后的数据也能看出问题:这条记录的CategoryName是asS,和你要匹配的asdasdasd1完全不搭边,但它却被查出来了。
| Id | DeviceCode | DeviceDesc | DeviceName | StoreId | StoreName | CategoryId | CategoryName |
|---|---|---|---|---|---|---|---|
| 3 | asdasd | 'asdasd' | 'asdasd' | '1' | dsfd | '21' | 'asS' |
最可能的排查方向
1. 先确认参数真的传对了
你的EF Core查询里有个判断逻辑:如果参数为空/空白,就跳过这个条件(返回true)。如果searchInput.CategoryName实际是空字符串或者null,那这个条件就等于没加,只会匹配StoreName的条件——而这条记录的StoreName是dsfd,刚好符合%dsfd%的匹配,自然会被返回。
建议你在执行查询前加个断点,或者打个日志,确认searchInput.StoreName和searchInput.CategoryName的值和你在SQL里用的完全一致(也就是dsfd和asdasdasd1)。
2. 查看EF Core实际生成的SQL
有时候EF Core生成的SQL和我们预期的不一样,最直接的方法就是看它到底发了什么SQL给数据库。如果是EF Core 5及以上版本,可以直接用ToQueryString()方法打印:
Console.WriteLine(serachresult.ToQueryString());
把打印出来的SQL拿到数据库里执行,看看会不会返回那条记录——如果会,说明EF Core生成的SQL和你手动写的有差异;如果不会,那问题可能出在查询后的内存处理(不过这种情况很少见)。
3. 检查Repository的GetAll()是否有隐藏逻辑
看看你的_deviceRepository.GetAll()、_storeRepository.GetAll()这些方法,有没有默认过滤或者额外的Include?比如有没有没过滤软删除的数据?或者有没有加了其他你没注意到的条件?如果你的手动SQL里默认隐含了某些过滤(比如IsDeleted=0),但Repository的GetAll()没加,也可能导致数据不一致。
解决方案
从你给出的信息来看,参数传入错误是最可能的原因——比如searchInput.CategoryName被误设为空值,导致Category的过滤条件失效。先优先排查这个:
- 断点验证
searchInput的两个字段值; - 如果参数没问题,就看EF Core生成的SQL,对比手动SQL找差异;
- 最后检查Repository的
GetAll()方法是否有隐藏逻辑。
举个例子,如果确实是searchInput.CategoryName为空,那你可以调整查询逻辑,确保只有当参数有效时才应用过滤,或者在参数传入前做校验,避免空值导致的意外结果。
内容的提问来源于stack exchange,提问作者Vivek Nuna

