反射的性能问题



我正在尝试动态搜索EF Core。我把整个东西做成这样的循环:

foreach (var i in vm.SearchProperties)
{
  if (result == null)
    result = db.MyTable.Where(x => x.GetType().GetProperty(i).GetValue(x, null).ToString().ToLower().StartsWith("MySearchString"));
  else
    result = result.Where(x => x.GetType().GetProperty(i).GetValue(x,null).ToString().ToLower().StartsWith(i.Suchfeld.ToLower(“mySearchString”)));
}

在我添加反射部分之前,它运行得相当快。当我将反射添加到它时,它的速度减慢了1000倍。有什么想法吗,我如何让它加速或围绕反射部分。

表达式太复杂了,LINQ to SQL转换器无法解释它,因此要对表中的每个项进行编译和执行,因此执行速度非常慢也就不足为奇了。

您需要基于要搜索的属性构建一个表达式树,然后构建一个Expression<Func<MyType, bool>>传递给您的Where(...)方法。这样,LINQ到SQL转换器就可以识别它。

试试这个:

ParameterExpression param = Expression.Parameter(typeof(MyType));
MethodInfo stringStartsWith = typeof(string).GetMethods().First(m => m.Name == "StartsWith" && m.GetParameters().Length == 1);
PropertyInfo firstProp = typeof(MyType).GetProperty(vm.SearchProperties.First());
MemberExpression firstMembAccess = Expression.Property(param, firstProp);
MethodCallExpression firstStartsWithExpr = Expression.Call(firstMembAccess, stringStartsWith, Expression.Constant(mySearchString));
Expression current = firstStartsWithExpr;
foreach (string s in vm.SearchProperties.Skip(1))
{
    PropertyInfo prop = typeof(MyType).GetProperty(s);
    MemberExpression membAccess = Expression.Property(param, prop);
    MethodCallExpression startsWithExpr = Expression.Call(membAccess, stringStartsWith, Expression.Constant(mySearchString));
    current = Expression.OrElse(current, startsWithExpr);
}
Expression<Func<MyType, bool>> mySearchExpression = Expression.Lambda<Func<MyType, bool>>(current, param);
result = db.MyTable.Where(mySearchExpression);

注意:MyType指的是你的实体类型

正如人们已经回答的那样,反射不能在IQueryable中使用。

将数据加载到内存中,并执行Where子句。

类似于您执行了以下代码(在where子句之前添加ToList()):

foreach (var i in vm.SearchProperties)
{
  if (result == null)
    result = db.MyTable.ToList().Where(x => x.GetType().GetProperty(i).GetValue(x, null).ToString().ToLower().StartsWith("MySearchString"));
  else
    result = result.ToList().Where(x => x.GetType().GetProperty(i).GetValue(x,null).ToString().ToLower().StartsWith(i.Suchfeld.ToLower(“mySearchString”)));
}

@Mr Anderson是对的。你需要用表达式树代替反射。

然而,使用表达式树有时可能过于复杂而难以构建。

免责声明:我是项目Eval-Expression的所有者。净

这个项目允许你在运行时计算和执行动态表达式。

简而言之,可以将动态字符串传递给where子句。

Wiki: Eval-Expression。. NET - LINQ Dynamic

foreach (var i in vm.SearchProperties)
{
  if (result == null)
    result = db.MyTable.Where(x => "x." + i + ".ToLower().StartsWith('MySearchString')");
  else
    result = result.Where(x => "x." + i + ".ToLower().StartsWith('MySearchString')");
}

相关内容

  • 没有找到相关文章

最新更新