不支持使用输入类型1的输入和类型2的检查的LINQ抛出TypeAs表达式 [英] LINQ throwing TypeAs expression with input of type 1 and check of type 2 is not supported

查看:61
本文介绍了不支持使用输入类型1的输入和类型2的检查的LINQ抛出TypeAs表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此行为我提供 不支持输入类型为User且检查类型为SoftDeleteEntity的'TypeAs'表达式 :

This line is giving me The 'TypeAs' expression with an input of type User and a check of type SoftDeleteEntity is not supported:

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

这里是里面.部分过滤的类型为IQueriable<User>.附加过滤器的类型为Expression<Func<User, bool>>,并且所传递的实际表达式(根据调试器)为!((x as SoftDeleteEntity).IsDeleted).用户继承SoftDeleteEntity.我认为我不会丢失任何相关信息,但是如果让我知道,我会详细说明.我了解必须存在一个隐式强制转换,该转换在某处不起作用,但我找不到它.

Here's what's in there. partiallyFiltered is of type IQueriable<User>. Additional filter is of type Expression<Func<User, bool>> and the actual expression being passed (as per debugger) is !((x as SoftDeleteEntity).IsDeleted). User inherits SoftDeleteEntity. I don't think I'm missing any relevant information but if I am let me know and I will elaborate. I understand that there must be an implicit cast that doesn't work somewhere but I can't find it.

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

here's the declaration of the expression, all entities are 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;
}

推荐答案

不幸的是,您将不得不动态地执行此操作.泛型(再加上Entity Framework对类型转换的明显恐惧)将不允许您以静态方式编写所需的代码.因此,请尝试以下方法:

Unfortunately, you're going to have to do this dynamically. Generics (combined with Entity Framework's apparent fear of typecasting) won't allow you to write the code you want in a static manner. So try this instead:

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).

What this code does is dynamically generates the expression you're looking for without having to express a typecast; the expression will already be strongly-typed to the specific entity type (like User) when it gets walked by Entity Framework.

编辑:关于为什么使用的原因,唯一危险的解释是,在代码停止按预期工作之前,您在DefaultFilter函数仅在客户端上运行,而未通过Entity Framework转换为SQL.在此过程中的某个地方,使用过滤器表达式的代码开始将其应用于表示实体集合的IQueryable<T>,而不是内存中的IEnumerable<T>(或类似)集合.您所展示的代码可以使用LINQ to Objects来正常工作,但不能使用Entity Framework.

As to why the code used to work, the only hazardable explanation is that before the code stopped working as expected, the lambda expression you created in the DefaultFilter function was only being run on the client, and not translated to SQL by Entity Framework. Somewhere along the way, code that consumes the filter expression began applying it to an IQueryable<T> representing an entity collection, as opposed to an IEnumerable<T> (or similar) collection in memory. The code as you presented it would work correctly using LINQ to Objects, but not Entity Framework.

这篇关于不支持使用输入类型1的输入和类型2的检查的LINQ抛出TypeAs表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆