C#使用带枚举参数的表达式实现IQueryable映射时类型转换报错
报错原因
你遇到的编译错误是IQueryable.Select的重载匹配错误导致的:
- 针对
IQueryable<User>调用Select方法时,如果你要传入的映射表达式只处理序列中的元素本身,应该使用入参只有User类型的Expression<Func<User, UserData>>类型的表达式,而你最初定义的s_entityToDataExpression是带两个入参(User、UserDataGroupType)的表达式,不匹配该重载的参数要求。 - 编译器匹配不到对应重载时,会尝试匹配其他可用的Select重载:LINQ原生提供了带索引的Select重载,签名为
Select<TSource, TResult>(IQueryable<TSource>, Expression<Func<TSource, int, TResult>>),第二个int参数代表元素在序列中的索引,编译器误以为你要调用这个重载,才会提示你需要把表达式转换为第二个参数为int的类型,这个int和你定义的UserDataGroupType枚举的底层类型没有关系。
方案说明
你后续修改的写法是正确的:
不要把UserDataGroupType作为映射表达式的入参,而是把它作为构建表达式的外部参数,每次调用时生成仅包含符合枚举要求的映射逻辑的单参数表达式,这样既符合Select的参数要求,也能让EF等ORM正确把表达式翻译为SQL执行。
修正后的可运行代码:
private static Expression<Func<User, UserData>> GetToDataExpression(UserDataGroupType dataGroups) => (entity) => new UserData { Id = entity.Id, State = entity.State, Role = entity.Role.ToData(), BaseData = dataGroups.HasFlag(UserDataGroupType.Base) ? entity.ToDataBase() : null, BirthData = dataGroups.HasFlag(UserDataGroupType.Birth) ? entity.ToDataBirth() : null, AddressData = dataGroups.HasFlag(UserDataGroupType.Address) ? entity.ToDataAddress() : null, ExtendedData = dataGroups.HasFlag(UserDataGroupType.Extended) ? entity.ToDataExtended() : null, }; public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) => queryable.Select(GetToDataExpression(dataGroups));
内容的提问来源于stack exchange,提问作者Perrier
相关产品推荐
相关产品推荐

