微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

包含另一个 lambda 的 Lambda IfThenElse 表达式用于 SetQueryFilter()

如何解决包含另一个 lambda 的 Lambda IfThenElse 表达式用于 SetQueryFilter()

我的目标是为 IMutableEntityType 设置过滤器,我在其中按 CurrentTenantId 列值选择数据行。 有关更多上下文,请参阅:https://github.com/dotnet/efcore/issues/23718

这已经由我完成了:

var parameter = Expression.Parameter(entityType.ClrType,"p");
                
// Todo: This filter is working,but we must prevent filtering with TenantId = 0
var workingFilter = Expression.Lambda(
    Expression.Equal(
        Expression.Property(parameter,colName),// See https://github.com/dotnet/efcore/issues/23718
        Expression.MakeMemberAccess(Expression.Constant(myContext),currentTenantIdMemberInfo)
        ),parameter);

entityType.SetQueryFilter(filter);

但我想获取所有实体如果 TenantId == 0,所以我写了这个 Lambda:

var conditionalExpression = Expression.IfThenElse(
    // Check if TenantId > 0
    Expression.GreaterThan(
        Expression.MakeMemberAccess(Expression.Constant(myContext),currentTenantIdMemberInfo),Expression.Constant((long) 0)
        ),// build filter: (p) => p.{colName} == {myContext.CurrentTenantId}
    // i.e. (p) => p.TenantId == 123)
    Expression.Lambda(
        Expression.Equal(
            Expression.Property(parameter,// See https://github.com/dotnet/efcore/issues/23718
            Expression.MakeMemberAccess(Expression.Constant(myContext),currentTenantIdMemberInfo)
            )//,),// TenantId <= 0,so act like (p => p)
    Expression.Lambda(Expression.Constant(parameter)) // just p // Todo: Not working
    //Expression.Lambda(Expression.Constant(parameter),parameter) // p => p // Todo: Also not working...
);

var filter = Expression.Lambda(conditionalExpression);

但是在调用 entityType.SetQueryFilter(filter); 之后我有 InvalidOperationException

'The filter expression '() => IIF((value(My.Project.MyContext).CurrentTenantId > 0),() => (p.TenantId == value(My.Project.MyContext).CurrentTenantId),() => p)' specified for entity type 'MyEntity' is invalid. The expression must accept a single parameter of type 'My.Project.MyEntity' and return bool.'

我的问题是 - 我如何才能实现我的目标?

解决方法

类似的东西。您错过了向 Lambda 添加 parameter 并且在 lambda 使用中犯了错误。还选择了最短的方法来做到这一点。

var parameter = Expression.Parameter(entityType.ClrType,"p");

// EF just needs to know that you have member access to DbContext
var contextExpr = Expression.Constant(null,typeof(MyContext));
var tenantExpr = Expression.MakeMemberAccess(contextExpr,currentTenantIdMemberInfo);

var conditionalExpression = Expression.OrElse(
    // Check if TenantId <= 0
    Expression.LessThanOrEqual(
        tenantExpr,Expression.Constant((long) 0)
        ),Expression.Equal(
            Expression.Property(parameter,colName),tenantExpr
        )
    )
);

var filter = Expression.Lambda(conditionalExpression,parameter);

entityType.SetQueryFilter(filter);

此外,您并不孤单,很多图书馆已经完成了这项任务,例如 ASP.NET Boilerplate

为了简化此类任务,我强烈建议使用表达式树可视化工具: https://github.com/agileobjects/ReadableExpressions https://github.com/zspitz/ExpressionTreeVisualizer

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。