【问题标题】:Using reflection throws error in EF Core 3在 EF Core 3 中使用反射会引发错误
【发布时间】:2020-09-24 16:48:36
【问题描述】:

我们以前使用反射来创建 linq 查询,例如对于 GetById 方法:

private IQueryable<T> GetQueryById(TKey id)
{
    var query = _dbset; //DbSet<T>

    var keyNames = _context.Model
            .FindRuntimeEntityType(typeof(T))
            .FindPrimaryKey()
            .Properties
            .Select(x => x.Name)
            .ToList();

    if (keyNames.Count() == 1)
    {
        query = query.Where(e => e.GetType().GetProperty(keyNames[0]).GetValue(e, null)
           .Equals(id)); //throws error
    }
        
    return query;
}

这在 EF Core 3 中似乎不再适用:

LINQ 表达式 'DbSet .Where(c => c.GetType().GetProperty(__get_Item_0).GetValue( 对象:c, index: null).Equals((object)__id_1))' 无法翻译。

是否可以重写查询以使 EF Core 不报错?

【问题讨论】:

  • 出于好奇,您之前的“工作”解决方案的性能如何?它不仅对每个项目进行反射,而且在检索内存中的整个表之后也会这样做。在 SO 或 EF Core 文档中搜索“客户端评估”以及它在 EFC 3.0 中被删除的原因。那么如何正确地重写查询呢,你必须构建表达式,例如这里stackoverflow.com/questions/42240968/…

标签: c# linq reflection entity-framework-core


【解决方案1】:

你必须动态创建谓词:

private IQueryable<T> GetQueryById(TKey id)
{
    IQueryable<T> query = _dbset; //DbSet<T>

    var keyNames = _context.Model
            .FindRuntimeEntityType(typeof(T))
            .FindPrimaryKey()
            .Properties
            .Select(x => x.Name)
            .ToList();

    if (keyNames.Count == 1)
    {
        var keyExpression = Expression.Constant(id);
        var entityParam   = Expression.Parameter(typeof(T), "e");
        var body          = Expression.Equal(Expression.PropertyOrField(entityParam, keyNames[0]), keyExpression);
        var predicate     = Expression.Lambda<Func<T, bool>>(body, entityParam);

        query = query.Where(predicate); 
    }
    else
      // better to throw exception
      throw new Exception($"Cannot find entity key.");
        
    return query;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2021-06-11
    • 2021-09-24
    • 2022-11-01
    • 2018-02-03
    • 2020-01-10
    相关资源
    最近更新 更多