这一行给了我 'TypeAs'表达式,其输入类型为User,不支持类型为SoftDeleteEntity的检查 :
var test = this.partiallyFiltered.Where(additionalFilter).ToList();
这里有什么。 partiallyFiltered的类型为IQueriable<User>
。附加过滤器的类型为Expression<Func<User, bool>>
,并且传递的实际表达式(根据调试器)为!((x as SoftDeleteEntity).IsDeleted)
。用户继承SoftDeleteEntity。我不认为我错过任何相关信息,但如果我告诉我,我会详细说明。我明白必须有一个隐含的演员在某个地方不起作用,但我找不到它。
编辑:这里是表达式的声明,所有实体都是IEntity。
public static Expression<Func<TEntity, bool>> DefaultFilter<TEntity>()
where TEntity : IEntity
{
if (typeof(SoftDeleteEntity).IsAssignableFrom(typeof(TEntity)))
return x => !(x as SoftDeleteEntity).IsDeleted;
else return x => true;
}
答案 0 :(得分:2)
不幸的是,你必须动态地这样做。泛型(与实体框架明显害怕类型转换相结合)将不允许您以静态方式编写所需的代码。所以试试这个:
using System.Linq.Expressions;
public static Expression<Func<TEntity, bool>> DefaultFilter<TEntity>()
where TEntity : IEntity
{
if (typeof(SoftDeleteEntity).IsAssignableFrom(typeof(TEntity)))
return DefaultFilterSoftDelete<TEntity>();
else return x => true;
}
public static Expression<Func<TEntity, bool>> DefaultFilterSoftDelete<TEntity>()
where TEntity : IEntity
{
var parameterExpression = Expression.Parameter(typeof(TEntity));
var propertyExpression = Expression.Property(parameterExpression,
"IsDeleted");
var notExpression = Expression.Not(propertyExpression);
var lambdaExpression = Expression.Lambda<Func<TEntity, bool>>(notExpression,
parameterExpression);
return lambdaExpression;
}
此代码的作用是动态生成您正在寻找的表达式,而无需表达类型转换;当表达式被实体框架遍历时,表达式已经强类型化为特定的实体类型(如User
)。
编辑:至于为什么代码使用工作,唯一可以解释的是,在代码停止按预期工作之前,您在{中创建的lambda表达式{1}}函数仅在客户端上运行,而不是由Entity Framework转换为SQL。在此过程中,使用过滤器表达式的代码开始将其应用于表示实体集合的DefaultFilter
,而不是内存中的IQueryable<T>
(或类似)集合。您提供的代码可以使用LINQ to Objects正常工作,但不能使用Entity Framework。
答案 1 :(得分:1)
所以我想出了答案,灵感来自亚当的回答。我想出的解决方案如下:
var function = additionalFilter.Compile();
var test = this.partiallyFiltered.Where(x => function(x));
此代码仅对每个实体类型使用一次,因此在此处编译它似乎不是问题。与其他建议的解决方案相比,这似乎是一个不那么繁琐的解决方案或需要较少重复的解决方案,因此我将在2天内接受它,除非其他人提出我的代码过去工作时间最长的真正原因停止工作。这段代码可以工作,但它没有解释任何东西,并且Adam的解释非常有意义,除了我之前使用静态定义的过滤器,我可以从我的历史中看到它的代码从未被修改过。只修改了我的模型。
编辑:正如adams所说,编译后的过滤器不会被转换为sql(我在想什么),因此只能在本地运行,所以这毕竟不是答案