不支持使用类型1的输入和类型2的检查的LINQ抛出TypeAs表达式

这一行给了我‘TypeAs’表达式,其输入类型为User,不支持类型为SoftDeleteEntity的检查

var test = this.partiallyFiltered.Where(additionalFilter).ToList(); 

这就是那里的东西。 partiallyFiltered的类型为IQueriable 。 附加filter的类型为Expression<Func> ,并且传递的实际表达式(根据调试器)是!((x as SoftDeleteEntity).IsDeleted) 。 用户inheritanceSoftDeleteEntity。 我不认为我错过任何相关信息,但如果我告诉我,我会详细说明。 我明白必须有一个隐含的演员在某个地方不起作用,但我找不到它。

编辑:这里是表达式的声明,所有实体都是IEntity。

 public static Expression<Func> DefaultFilter() where TEntity : IEntity { if (typeof(SoftDeleteEntity).IsAssignableFrom(typeof(TEntity))) return x => !(x as SoftDeleteEntity).IsDeleted; else return x => true; } 

不幸的是,你将不得不动态地这样做。 generics(与entity framework明显害怕类型转换相结合)将不允许您以静态方式编写所需的代码。 所以试试这个:

 using System.Linq.Expressions; public static Expression> DefaultFilter() where TEntity : IEntity { if (typeof(SoftDeleteEntity).IsAssignableFrom(typeof(TEntity))) return DefaultFilterSoftDelete(); else return x => true; } public static Expression> DefaultFilterSoftDelete() where TEntity : IEntity { var parameterExpression = Expression.Parameter(typeof(TEntity)); var propertyExpression = Expression.Property(parameterExpression, "IsDeleted"); var notExpression = Expression.Not(propertyExpression); var lambdaExpression = Expression.Lambda>(notExpression, parameterExpression); return lambdaExpression; } 

这段代码的作用是动态生成你正在寻找的表达式,而不必表达类型转换; 当表达式被entity framework遍历时,表达式已经强类型化为特定的实体类型(如User )。

编辑:至于为什么代码工作,唯一可以解释的是,在代码停止按预期工作之前,您在DefaultFilter函数中创建的lambda表达式只在客户端上运行,而不是由Entity Framework转换为SQL 。 在此过程中,使用filter表达式的代码开始将其应用于表示实体集合的IQueryable ,而不是内存中的IEnumerable (或类似)集合。 您提供的代码可以使用LINQ to Objects正常工作,但不能使用Entity Framework。

所以我想出了答案,灵感来自亚当的回答。 我想出的解决方案如下:

 var function = additionalFilter.Compile(); var test = this.partiallyFiltered.Where(x => function(x)); 

此代码仅对每个实体类型使用一次,因此在此处编译它似乎不是问题。 与其他建议的解决方案相比,这似乎是一个不那么繁琐的解决方案或需要较少重复的解决方案,因此我将在2天内接受它,除非有其他人提出我的代码以前工作时间最长的真正原因停止工作。 这段代码可以工作,但它没有解释任何东西,并且Adam的解释非常有意义,除了我之前使用静态定义的filter,我可以从我的历史中看到它的代码从未被修改过。 只修改了我的模型。

编辑:正如亚当斯所指出的,编译后的filter不会被翻译成sql(我在想什么),因此只会在本地运行,所以这毕竟不是答案