展开实体框架 6 中的查询表达式
本文关键字:查询 查询表 表达式 实体 框架 | 更新日期: 2023-09-27 18:35:13
我有ParentItem
应该应用安全修整。因此,有一个SecurityTrimmingExpressionFactory
将为父元素构建一个Expression<Func<ParentItem, bool>>
:
安全性修整表达式工厂
public static Expression<Func<ParentItem, bool>> CreateTrimming(currentUser)
{
return parentItem => parentItem.OwnerId == currentUser.Id;
}
在我的 WebAPI 控制器中,我想接收父元素的子项。我会这样写的正常方式
WebAPI 控制器 (Get)
return Entities.ChildItems.Where(c => c.parentId == <some id>);
完全没有问题,但没有安全修整。
如果我想在这里应用我的安全修整(目前我正在使用 LinqKit 使用父项构建表达式树)
具有修剪功能的 WebAPI 控制器 (Get)
var expr = TrimmingExpressionsFactory.CreateParentTrimming(this.CurrentUser);
return Entities.ChildItems
.AsExpandable()
.Where(childItem => expr.Invoke(childItem.ParentItem)
.Where(c => c.parentId == <some id>)
);
一切正常。
现在的问题是外部库(如LinqKit)在当前环境中是被禁止的(在我看来:错误的决策;))。没有外部库,有没有另一种方法可以使用依赖实体扩展或调用查询表达式?
已经尝试使用.AsEnumerable()
来解决此问题(通常在 Web 中发现这是解决方法),但对于大型数据集来说,这不是可接受的解决方案。
您可以使用我的答案中的小助手实用程序将表达式的一部分定义为 c# 中的变量:
public static class ExpressionUtils
{
public static Expression<Func<TOuter, TResult>> Bind<TOuter, TInner, TResult>(this Expression<Func<TOuter, TInner>> source, Expression<Func<TInner, TResult>> resultSelector)
{
var body = new ParameterExpressionReplacer { source = resultSelector.Parameters[0], target = source.Body }.Visit(resultSelector.Body);
var lambda = Expression.Lambda<Func<TOuter, TResult>>(body, source.Parameters);
return lambda;
}
public static Expression<Func<TOuter, TResult>> ApplyTo<TInner, TResult, TOuter>(this Expression<Func<TInner, TResult>> source, Expression<Func<TOuter, TInner>> innerSelector)
{
return innerSelector.Bind(source);
}
class ParameterExpressionReplacer : ExpressionVisitor
{
public ParameterExpression source;
public Expression target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == source ? target : base.VisitParameter(node);
}
}
}
示例案例中的用法为:
var filter = TrimmingExpressionsFactory.CreateParentTrimming(this.CurrentUser)
.ApplyTo((ChildItem childItem) => childItem.ParentItem);
return Entities.ChildItems
.Where(filter)
.Where(c => c.parentId == <some id>)
);