如何去除EF Core生成的SQL中Guid类型ID查询的CONVERT转换操作
问题根本原因
原有写法调用了Guid列的ToString()方法,EF Core为了匹配字符串对比逻辑,才会在SQL中生成CONVERT(VARCHAR(36), [c].[ID])转换,会导致ID列的索引失效。
之前两种写法报错的核心原因是动态Linq(System.Linq.Dynamic.Core)的类型匹配规则限制:传入的集合类型要和属性类型完全一致,且低版本动态Linq对泛型集合的Contains方法解析存在兼容问题。
正确实现方案
方案1:修复动态Linq写法
先确保你使用的System.Linq.Dynamic.Core版本≥1.2.18,然后按以下代码调整:
// 处理前端传入的ID字符串,反序列化为和实体列类型一致的Guid数组 Guid[] idList = JsonConvert.DeserializeObject<Guid[]>(filter.Value.Replace("array", string.Empty)); // 动态Linq直接匹配Guid类型,无需类型转换 Filters.Add(_context.Filter<TEntity>(x => x.Where($"@0.Contains({exactName})", idList)));
如果你的实体ID是可空Guid?类型,把idList的类型改为Guid?[]即可。
这种写法生成的SQL会直接匹配Guid类型,没有转换逻辑:
SELECT [c].[FirstName], [c].[ID], [c].[LastName] FROM [Employee] AS [c] WHERE NOT ([c].[IsDeleted] = CAST(1 AS bit)) AND [c].[ID] IN ('ef47913f-8960-46ad-f8ff-08d865b62242', '1617bed9-4369-44eb-b605-08d895a537c9', ...)
方案2:表达式树实现(无动态Linq兼容问题)
如果动态Linq还是报错,可以直接构造强类型表达式树,完全规避字符串解析的问题:
// 解析ID数组 Guid[] idList = JsonConvert.DeserializeObject<Guid[]>(filter.Value.Replace("array", string.Empty)); // 构造 x => idList.Contains(x.{exactName}) 强类型表达式 var param = Expression.Parameter(typeof(TEntity), "e"); var prop = Expression.Property(param, exactName); var containsMethod = typeof(Enumerable) .GetMethods(BindingFlags.Public | BindingFlags.Static) .First(m => m.Name == nameof(Enumerable.Contains) && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(Guid)); var filterExp = Expression.Lambda<Func<TEntity, bool>>( Expression.Call(containsMethod, Expression.Constant(idList), prop), param ); // 加入过滤器 Filters.Add(_context.Filter<TEntity>(x => x.Where(filterExp)));
内容的提问来源于stack exchange,提问作者Xatrix
相关产品推荐
相关产品推荐

