在EntityFramework 6

时间:2016-02-17 15:30:27

标签: c# entity-framework rest asp.net-web-api entity-framework-6

我有ParentItem s应该应用安全修整。 因此,SecurityTrimmingExpressionFactory会为父元素构建Expression<Func<ParentItem, bool>>

SecurityTrimmingExpressionFactory

public static Expression<Func<ParentItem, bool>> CreateTrimming(currentUser)
{
   return parentItem => parentItem.OwnerId == currentUser.Id;    
}

在我的WebAPI控制器中,我希望接收父元素的子项。 正常的方式我会像这样写

WebAPI控制器(获取)

return Entities.ChildItems.Where(c => c.parentId == <some id>);

完全没问题,但没有安全修整。

如果我想在此处应用我的安全修整(目前我正在使用LinqKit使用父项构建表达式树)

带有修剪的WebAPI控制器(获取)

var expr = TrimmingExpressionsFactory.CreateParentTrimming(this.CurrentUser);
return Entities.ChildItems
                       .AsExpandable()
                       .Where(childItem => expr.Invoke(childItem.ParentItem)
                       .Where(c => c.parentId == <some id>)
                );

一切正常。

现在问题是在当前环境中禁止使用外部库(如LinqKit)(在我看来:错误的决定;))。 是否有另一种方法没有外部库来扩展或使用dependend Entities调用查询表达式?

已经尝试使用.AsEnumerable()解决此问题(通常在网络中发现这是一种解决方法),但对于大型数据集来说,这不是一个可接受的解决方案。

1 个答案:

答案 0 :(得分:1)

您可以使用我对Define part of an Expression as a variable in 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>)
);