EF 6.1.1, Interceptors and visitors RRS feed

  • Question

  • I'm trying to implement authorization by interceptors in Entity Framework 6.1.1.

    This is my code:

    public class DemoDbConfiguration : DbConfiguration
    	public DemoDbConfiguration()
    		AddInterceptor(new AuthorizationInterceptor());
    public class DemoContext : DbContext
    	public DbSet<Demo> Demos { get; set; }
    	public DbSet<Auth> Auths { get; set; }
    public class Demo
    	public int Id { get; set; }
    	public string Name { get; set; }
    	public int DomainId { get; set; }
    	public Domain Domain { get; set; }
    public class Domain
    	public int Id { get; set; }
    	public string Name { get; set; }
    public class Auth
    	[Key, Column(Order = 0)]
    	public int DomainId { get; set; }
    	[Key, Column(Order = 1)]
    	public int IdentityId { get; set; }
    	[Key, Column(Order = 2)]
    	public int FunctionKey { get; set; }
    	public bool? Value { get; set; }
    public class AuthorizationInterceptor : IDbCommandTreeInterceptor
    	public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
    		if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
    			var queryCommand = interceptionContext.Result as DbQueryCommandTree;
    			if (queryCommand != null)
    				var newQuery = queryCommand.Query.Accept(new AuthorizationQueryVisitor());
    				interceptionContext.Result = new DbQueryCommandTree(
    public class AuthorizationQueryVisitor : DefaultExpressionVisitor
    	public override DbExpression Visit(DbScanExpression main)
    		//TODO - Use annotations to determine if ElementType is Authorizable
    		if (main.Target.ElementType.Name == "Demo")
    			var mainBinding = main.BindAs("main");
    			var auth = main.Target.EntityContainer.GetEntitySetByName("Auth", false).Scan();
    			var authBinding = auth.BindAs("auth");
    			var join = mainBinding.InnerJoin(
    			var selectPairs = main.Target.ElementType.Members
    				.Select(mem =>
    					new KeyValuePair<string, DbExpression>(
    			var select = join.Select(ex => DbExpressionBuilder.NewRow(selectPairs));
    			return select;
    			//TODO - Implement filter (WHERE clause)
    		} else return base.Visit(main);

    I want to reproduce this SQL statement:

    SELECT d.Id, d.Name, d.DomainId
    FROM Demoes as d
    INNER JOIN Auths as a
    ON d.DomainId = a.DomainId
    WHERE FunctionKey = 1 AND IdentityId = 1 AND Value = 1

    WHERE clause is not implemented yet and the constants must be replaced by proper values.

    I'm getting this error:

    ArgumentException: The referenced variable 'main' is not defined in the current scope.

    How i can define the 'main' and 'auth'' variables?

    What is wrong there?

    Is this possible to implement with this approach?


    • Edited by Oscar Jim Thursday, June 26, 2014 1:47 PM
    Thursday, June 26, 2014 1:18 PM

All replies

  • Hello,

    For reproducing this SQL statement, I think using the linq2entities is enough as:

    var result = (from demo in db.Demos
                                  join auth in db.Auths on demo.DomainId equals auth.DomainId
                                  where auth.FunctionKey == 1 && auth.IdentityId == 1 && auth.Value == true
                                  select demo).ToList();

    As you said you want to implement authorization by interceptors, I don’t understand why you need to do it.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, June 27, 2014 7:28 AM
  • Hello Fred:

    Yes, your linq sentence is equivalent to my sql code but i'm trying to implement this functionality with interceptors and visitors. 

    I can modify all methods in all controllers for implement the authorization filters but i want implement it in a general manner for abstract and centralize the implementation on entire system at one time.

    I think that this code is compliant since latest stable version (6.1.1) of Entity Framework. I was inspired with this session at Build 2014 by Rowan Miller: 

    Rowan show us how implement soft delete functionality using interceptors and visitors. All entities in our solution can be marked with SoftDeleteAttribute and automatically the delete sentences wil be converted into update sentences to mark database rows as deleted but not deleted definitively from database.

    I want to implement similar functionality but for authorization purpose.


    • Edited by Oscar Jim Friday, June 27, 2014 9:05 AM
    Friday, June 27, 2014 8:56 AM
  • Hi,

    For if your idea is feasible, you can add a comment at below the video.

    Monday, June 30, 2014 7:01 AM
  • Hello Oscar,

    Were you able to accomplish what you were trying?. I have the same requirement...



    Wednesday, December 31, 2014 8:24 PM
  • No, sorry Yosel :(

    I have decided implement this out of interception system, but i'm building the expression on the fly anyway.

    This is the code to check if a field of an entity, is contained in a values array:

            private Expression<Func<TEntity, bool>> BuildForeignKeysContainsPredicate<T>(List<T> foreignKeys, PropertyInfo property)
                Expression<Func<TEntity, bool>> result = default(Expression<Func<TEntity, bool>>);
                    ParameterExpression entityParameter = Expression.Parameter(typeof(TEntity));
                    ConstantExpression foreignKeysParameter = Expression.Constant(foreignKeys, typeof(List<T>));
                    MemberExpression memberExpression = Expression.Property(entityParameter, property);
                    Expression convertExpression = Expression.Convert(memberExpression, typeof(T));
                    MethodCallExpression containsExpression = Expression.Call(foreignKeysParameter
                        , "Contains", new Type[] { }, convertExpression);
                    result = Expression.Lambda<Func<TEntity, bool>>(containsExpression, entityParameter);
                    if (typeof (INullable).IsAssignableFrom(property.PropertyType) ||
                        (property.PropertyType.IsGenericType &&
                         property.PropertyType.GetGenericTypeDefinition() == typeof (Nullable<>)))
                        var arg = Expression.Parameter(typeof (TEntity));
                        var prop = Expression.Property(arg, property);
                        result = Expression.Lambda<Func<TEntity, bool>>(
                                Expression.Constant(null, prop.Type)),
                } catch (Exception ex)
                    throw ex;
                return result;

    I try to explain you this method:
    The method gets an array of values to check and a PropertyInfo that represent the field (column in SQL) in which we make the "Contains" check.

    On this call, the method returns an expression that checks if field "Id" have value "1" or "2"
    In addition, if type of property defined by PropertyInfo parameter is nullable, the result expression contains a "AND" clausule that exclude all null values

    I suppose that this is not the same that the original topic, but i hope help you.

    Happy new year!

    Friday, January 2, 2015 10:50 AM