C# 实体框架授权IDBComandTreeInterceptor

C# 实体框架授权IDBComandTreeInterceptor,c#,entity-framework,linq,entity-framework-6,linq-to-entities,C#,Entity Framework,Linq,Entity Framework 6,Linq To Entities,我试图实现一种通用方法,将授权SQL过滤器添加到所有实体框架查询中。 为此,我使用IDbCommandTreeInterceptor和DefaultExpressionVisitor。 这些模型是基本的:我们所有的实体都有一个RegionID,我们在Db上下文中有一个DynRegions实体集,其中包含用户可以访问的所有区域 因此,我想在下面的linq查询中动态添加Any过滤器(它生成一个SQL SELECT EXISTS): 我从以下代码开始: public class RegionsInte

我试图实现一种通用方法,将授权SQL过滤器添加到所有实体框架查询中。 为此,我使用IDbCommandTreeInterceptor和DefaultExpressionVisitor。 这些模型是基本的:我们所有的实体都有一个RegionID,我们在Db上下文中有一个DynRegions实体集,其中包含用户可以访问的所有区域

因此,我想在下面的linq查询中动态添加Any过滤器(它生成一个SQL SELECT EXISTS):

我从以下代码开始:

public class RegionsInterceptor : IDbCommandTreeInterceptor
{
    public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
    {
        if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace) return;

        var queryCommand = interceptionContext.Result as DbQueryCommandTree;
        if (queryCommand == null) return;

        var dbContext = interceptionContext.DbContexts.FirstOrDefault() as CrmContext;
        if (dbContext == null) return;

        var newQuery = queryCommand.Query.Accept(new RegionsQueryVisitor(dbContext));
        interceptionContext.Result = new DbQueryCommandTree(
                                            queryCommand.MetadataWorkspace,
                                            queryCommand.DataSpace,
                                            newQuery);
    }
}

public class RegionsQueryVisitor : DefaultExpressionVisitor
{
    private readonly CrmContext dbContext;

    public RegionsQueryVisitor(CrmContext dbContext)
    {
        this.dbContext = dbContext;
    }

    public override DbExpression Visit(DbScanExpression expression)
    {
        var dbExpression = base.Visit(expression);

        var currentExpressionBinding = DbExpressionBuilder.Bind(dbExpression);
        var currentEntityRegionId = DbExpressionBuilder.Property(currentExpressionBinding.Variable, "RegionId");

        var rolesExpression = expression.Target.EntityContainer.GetEntitySetByName("DynRole", true).Scan();
        var rolesExpressionBinding = rolesExpression.Bind();

        var rolesRegionIdProperty = DbExpressionBuilder.Property(rolesExpressionBinding.Variable, "RegionId");
        var rolesUserIdProperty = DbExpressionBuilder.Property(rolesExpressionBinding.Variable, "UserId");
        var userIdParameter = DbExpressionBuilder.Constant("150293818FC844F89AB36D044988F146");

        var anyRolesExpression =
            rolesExpression.Any(p => 
                    DbExpressionBuilder.Equal(rolesUserIdProperty, userIdParameter)
                        .And(
                    DbExpressionBuilder.Equal(rolesRegionIdProperty, currentEntityRegionId)));


        var binding = expression.Bind();

        return binding.Filter(anyRolesExpression);
    }    
}
我得到一个错误:引用的变量“Var_2”未在当前范围中定义。 错误发生在以下行:

interceptionContext.Result = new DbQueryCommandTree(
                                             queryCommand.MetadataWorkspace,
                                             queryCommand.DataSpace,
                                             newQuery);
有什么想法吗?有人写过这样的拦截器/访问者吗? 如有任何帮助/建议,将不胜感激

谢谢,
亚历克斯似乎过于复杂了。如何通过添加安全条件来包装上下文查询创建?您好,我看了这篇文章,您到底在哪里挣扎?您可以以此为基础,将IsDeletedColumnName替换为RegionColumnName,将bool替换为int,然后从那里开始工作。你必须将RegionID传递给访客,心想。嗨,维塔利,你能澄清一下吗?在哪里创建上下文查询?不要使用上下文。直接联系e.t.c。相反,用户助手例程创建适当类型的泛型数据库集append where condition并将其作为可查询的返回。
interceptionContext.Result = new DbQueryCommandTree(
                                             queryCommand.MetadataWorkspace,
                                             queryCommand.DataSpace,
                                             newQuery);