如何将where子句与iqueryable< dynamic>一起使用

bkkx9g8r  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(283)

我使用带有反射的实体框架核心来动态生成一些表单。除了where子句外,一切正常。我得到以下错误:
表达式树不能包含动态操作
我可以通过将iqueryable转换为一个列表来解决这个问题,但这会引入我希望避免的不同问题。
这是我的密码:

public async void ViewCollection(PropertyInfo propertyInfo)
{
    Type propertyType = propertyInfo.PropertyType;
    InversePropertyAttribute inversePropertyAttribute = (InversePropertyAttribute)ReflectionHelpers.GetAttribute(propertyInfo, typeof(InversePropertyAttribute));

    //GET THE TYPE OF THE COLLECTION
    Type collectionType = propertyInfo.PropertyType.GenericTypeArguments[0];

    //GET THE INVERSE PROPERTY INFO
    PropertyInfo inverseProperty = collectionType.GetProperty(inversePropertyAttribute.Property);

    //GET THE FOREIGN KEY ATTRIBUTE FROM THE INVERSE PROPERTY
    ForeignKeyAttribute foreignKeyAttribute = (ForeignKeyAttribute)ReflectionHelpers.GetAttribute(inverseProperty, typeof(ForeignKeyAttribute));

    //GET THE FOREIGN KEY PROPERTY FROM THE FOREIGN KEY ATTRIBUTE
    PropertyInfo foreignKeyProperty = collectionType.GetProperty(foreignKeyAttribute.Name);

    //GET INCLUDED TYPE NAMES BY FOREIGN KEY
    IEnumerable<string> includedTypes = collectionType.GetProperties().Where(p => p.PropertyType.IsClass).Where(p => ReflectionHelpers.HasAttribute(p, typeof(ForeignKeyAttribute))).Select(r => r.Name);

    //GET THE DATA SET
    IQueryable<dynamic> items = ReflectionHelpers.GetDbCollectionByType(Db, collectionType);

    //INCLUDE THE INCLUDED TYPES BY NAME
    foreach (string includedType in includedTypes) items = items.Include(includedType);

    //THIS IS WHERE THE ERROR IS
    items = items.Where(i => foreignKeyProperty.GetValue(i, null) == PrimaryKeyProperty.GetValue(Item, null));

    await ShowCollection(collectionType, items, propertyInfo.Name);
}

我怎样才能解决这个问题而不改变我的类型列表?

y1aodyip

y1aodyip1#

你不能。iqueryable是语言集成查询(linq)的一部分—它是静态类型的,因此不能使用值类型。
iqueryable幕后是一个表达式树,它表示尚未执行的查询。表达式树部分表示查询。静态类型表示查询对其进行操作的数据。
最好的选择是使用expressiontreeapi手工构建表达式树。

c90pui9n

c90pui9n2#

不能在上面生成查询 dynamic 因为它在表达式树中本机不受支持。相反,你应该把你的工作建立在非泛型的基础上 IQueryable 或通用 IQueryable<object> . e、 g.如果 ReflectionHelpers.GetDbCollectionByType 正在呼叫 DbContext.Set<T> 动态地(类似于这里的efcore2.0中的动态访问表),您应该能够将它强制转换为 IQueryable<object> :

var items = (IQueryable<object>)ReflectionHelpers.GetDbCollectionByType(Db, collectionType);

添加 Where 子句中,不应在 predicate 表达式内使用反射调用,而应使用 Expression 类方法(从 System.Linq.Expressions 命名空间)。像这样:

// (object i) => (({collectionType})i).{ForeignKey} == Item.{PrimaryKey}
var parameter = Expression.Parameter(typeof(object), "i");
var body = Expression.Equal(
    Expression.Property(Expression.Convert(parameter, collectionType), foreignKeyProperty),
    Expression.Property(Expression.Constant(Item), PrimaryKeyProperty));
var predicate = Expression.Lambda<Func<object, bool>>(body, parameter);

然后

items = items.Where(predicate); // still IQueryable<object>

相关问题