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

时间:2013-06-21 19:16:45

标签: c# .net linq entity-framework

这一行给了我 '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;
}

2 个答案:

答案 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(我在想什么),因此只能在本地运行,所以这毕竟不是答案