【问题标题】:EF Core - search properties by stringEF Core - 按字符串搜索属性
【发布时间】:2021-11-04 10:24:50
【问题描述】:

我有一个包含几百列的表,我从客户端将多个“搜索”对象传递给用于查询该表的服务器。每个搜索对象都包含一个搜索词,以及与之匹配的属性名称。

我不确定如何在此处使用反射来使用 EF Core 查询属性。我尝试了以下但它不喜欢它。

var prop = <ENTITYTYPE>.GetProperty(search.Property);

query = context.<ENTITY>.Where(x => (string)prop.GetValue(x) == search.SearchTerm);

我在想我可能必须构建一个原始 SQL 查询,但我很想知道是否有一种方法可以让 EF Core 自行创建查询。当我在上面执行.ToList() 时,它说无法翻译查询。

任何帮助将不胜感激!

【问题讨论】:

  • 您不能在 EF Core 查询中使用反射,也不能像这样按名称传递属性。 Where 可以使用任何有效的表达式,因此您可以重写代码以将 Expression&lt;Func&lt;TEntity,bool&gt;&gt; 作为过滤器而不是字符串传递。您也可以使用 Dynamic LINQ 包来解析字符串表达式,但这会丢失任何类型的编译时检查

标签: c# .net-core entity-framework-core


【解决方案1】:

不推荐使用,见 cmets 我尝试了下面的示例,它对我有用

private void Test()
{

    Type myType = typeof(AktivEvents);

    PropertyInfo myPropInfo = myType.GetProperty("AutoReplyMessage");

    Func<AktivEvents, bool> func = (e) => (string)myPropInfo.GetValue(e) == "asdasd";


    var query = _dbService.AktivEvents.GetAll()
        .Where(func)
        .ToList();
}

它显然很脏,但这个想法很有效,有依赖关系

    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />

【讨论】:

  • 您根本没有使用 EF。无论GetAll() 是什么,它都会返回所有数据而不是DbSet。根本不可能将反射调用转换为 SQL。将所有内容加载到内存中根本不是解决方案。它可能适用于 10 行,但不适用于 1000 或 100K 行的表。
  • @PanagiotisKanavos 我使用存储库模式codewithshadman.com/repository-pattern-csharp,并在我的项目中使用数据库测试了示例,它可以正常工作
  • 不,它没有。该 anti 模式在内存中加载了所有 10/100K/1M 行。之后,您将使用 LINQ-to-Objects。将所有内容加载到内存中对于生产代码是不可接受的。这不仅会浪费客户端的 RAM,还会延迟返回结果,直到所有内容都加载完毕,更糟糕的是,会锁定整个表,直到所有数据都加载完毕。即使只需要一行。最后一部分可能会导致整个数据库的性能问题甚至死锁
  • @PanagiotisKanavos,是的,我查过了,没错
  • 您链接到的文章没有GetAll()。它使用Expression&lt;Func&lt;TEntity,bool&gt;&gt; 传递任意过滤器。 RepositoryUnitOfWork 类和方法本质上是 DbSet 和 DbContext 重命名,因为 DbSet 已经是一个 Repository 并且 DbContext 已经一个 Unit-of-Work
【解决方案2】:

这是一个基本的认识,应该会推动你朝着正确的方向前进:

public static IQueryable<T> AddFilter<T>(IQueryable<T> query, string propertyName, string searchTerm)
{
    var param = Expression.Parameter(typeof(T), "e");
    var propExpression = Expression.Property(param, propertyName);
    
    object value = searchTerm;
    if (propExpression.Type != typeof(string))
        value = Convert.ChangeType(value, propExpression.Type);

    var filterLambda = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(
            propExpression,
            Expression.Constant(value)
        ),
        param
    );

    return query.Where(filterLambda);
}

【讨论】:

  • 谢谢 - 我已经使用 Expressions。
猜你喜欢
  • 2022-02-27
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 2020-06-28
相关资源
最近更新 更多