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