EF6 SQL Server查询使用Contains时异常问题排查
问题描述
我有一个EF6 SQL Server查询,在传入List<int>类型的ID列表时表现异常:
- 当
bookGenieCategory为有效值时查询正常; - 当
selectedAges为空(count=0)时查询正常; - 但当
selectedAges包含ProductCategory.CategoryId列中存在的值时,Contains查询失效,无任何行返回。
注:AllocationCandidates是一个独立使用正常的视图,其定义如下:
CREATE VIEW dbo.AllocationCandidate AS SELECT p.ProductID, p.SKU as ISBN, p.Name as Title, pv.MSRP, pv.Price, pv.VariantID, pv.Inventory, ISNULL(plt.DateLastTouched, GETDATE()) AS DateLastTouched, JSON_VALUE(p.MiscText, '$.AgeId') AS AgeId, JSON_VALUE(p.MiscText, '$.AgeName') AS AgeName FROM dbo.Product AS p WITH (NOLOCK) INNER JOIN dbo.ProductVariant AS pv WITH (NOLOCK) ON pv.ProductID = p.ProductID LEFT OUTER JOIN dbo.KBOProductLastTouched AS plt WITH (NOLOCK) ON plt.ProductID = p.ProductID WHERE (ISJSON(p.MiscText) = 1) AND (p.Deleted = 0) AND (p.Published = 1) AND (pv.IsDefault = 1) GO
请问以下EF查询代码是否存在拼写错误或括号误用?
var returnList = (from ac in _db.AllocationCandidates join pc in _db.ProductCategories on ac.ProductID equals pc.ProductID where (bookGenieCategory == 0 || bookGenieCategory == pc.CategoryID) && (selectedAges.Count == 0 || selectedAges.Contains(pc.CategoryID)) orderby ac.AgeId, ac.DateLastTouched descending select ac).ToList();
问题排查与解决
这段EF代码存在字段误用的问题,并非括号或拼写错误:
在selectedAges.Contains(pc.CategoryID)这一行,错误地用了pc.CategoryID(产品分类ID)来匹配selectedAges(年龄ID列表)。根据视图定义,年龄ID存储在ac.AgeId字段中,而pc.CategoryID是产品所属分类的ID,两者属于完全不同的业务维度,自然无法匹配,导致查询无结果。
为什么其他场景能正常工作?
- 当
bookGenieCategory为有效值时:此时查询只受分类条件过滤,年龄条件因selectedAges.Count==0不生效,所以结果正常; - 当
selectedAges为空时:年龄条件直接跳过,只执行分类过滤,结果正常; - 只有当
selectedAges有值时,错误的字段匹配导致没有符合pc.CategoryID in selectedAges的行,所以返回空。
修正后的代码
var returnList = (from ac in _db.AllocationCandidates join pc in _db.ProductCategories on ac.ProductID equals pc.ProductID where (bookGenieCategory == 0 || bookGenieCategory == pc.CategoryID) && (selectedAges.Count == 0 || selectedAges.Contains(ac.AgeId)) // 这里改为ac.AgeId orderby ac.AgeId, ac.DateLastTouched descending select ac).ToList();
内容的提问来源于stack exchange,提问作者BedfordNYGuy
相关产品推荐
相关产品推荐

