【问题标题】:Reflection within IQueryable in .NET Core.NET Core 中 IQueryable 中的反射
【发布时间】:2020-09-23 05:08:27
【问题描述】:

我想知道下面的代码将如何工作以及性能如何。我基本上对第 4 行感兴趣。 linq 和属性信息如何协同工作?

换句话说,(int)prop.GetValue(a)a.SomeId 的工作方式是否相同,或者反射是否需要在检查值之前将所有内容都存储到内存中?

var prop = type.GetProperty("SomeId");

if (prop != null) 
{
     DbSet<T> dbSet = _dbContext.Set<T>();
     return dbSet.Where(a => (int)prop.GetValue(a) == 1);
}

【问题讨论】:

  • 取决于后备存储,上下文可能无法将表达式转换为底层查询语法(例如 SQL)。您可以考虑手动构建一个有效的表达式。

标签: linq .net-core reflection iqueryable


【解决方案1】:

换句话说,(int)prop.GetValue(a)a.SomeId 的工作方式相同

没有。

根据后备存储,上下文可能无法将该表达式 ((int)prop.GetValue(a)) 转换为底层查询语法,在大多数情况下是 SQL。

您可以考虑使用属性信息手动构建一个有效的表达式。

例如

//Assuming
Type type = typeof(T);

PropertyInfo prop = type.GetProperty("SomeId");
if (prop != null) {
    //need to build a => a.SomeId == 1

    // a =>
    ParameterExpression parameter = Expression.Parameter(type, "a");
    // a => a.SomeId
    MemberExpression property = Expression.Property(parameter, prop);
    // a => a.SomeId == 1
    BinaryExpression body = Expression.Equal(property, Expression.Constant(1));

    Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(body, parameter);

    DbSet<T> dbSet = _dbContext.Set<T>();

    return dbSet.Where(expression);
}

【讨论】:

  • 非常感谢@Nkosi,这就是我需要的答案。所以,我假设,通过这种方式,EF 生成 SQL 查询不会有问题。我的理解对吗?
  • @Elnoor 正确。通过构建表达式,EF 将能够生成所需的语法。
  • 太棒了,谢谢!现在我应该完成我的多租户:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 2018-03-26
  • 1970-01-01
  • 2018-11-21
  • 2023-03-06
  • 2023-01-30
相关资源
最近更新 更多