Learning Entity Framework 6 command tree interceptors

c# entity-framework entity-framework-6 interceptor

Question

This is purely a learning experiment (yay science!). This is not meant to actually be used anywhere. I want to learn how EF6's command tree interceptors work.

I'm trying to modify the intercepted command tree to add a "IsActive = 1" filter to all queries. I've noticed a serious deficiency in documentation on this sort of thing. Two questions:

How do I selectively intercept command trees for say, entities that implement an interface (such as IHasAnActiveProperty)? Right now I note that the interceptor is intercepting queries for the history context, which has nothing to do with my MyEntity.

How do I add my filter to all queries?

public class MyEntity
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Name { get; set; }

    public bool IsActive { get; set; }
}

public class MyDbContext : DbContext
{
    public DbSet<MyEntity> Entities { get; set; }

    public MyDbContext() : base("default") { }


    public MyDbContext(string nameOrConnectionString)
        : base(nameOrConnectionString) {}
}

public class MyConfiguration : DbConfiguration
{
    public MyConfiguration()
    {
        AddInterceptor(new MyInterceptor());
    }
}

public class MyInterceptor : IDbCommandTreeInterceptor
{
    public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
    {
        var query = interceptionContext.Result as DbQueryCommandTree;
        if (query != null)
        {
            Debug.WriteLine("##################");
            Debug.WriteLine("DataSpace: {0}", interceptionContext.Result.DataSpace);
            Debug.WriteLine(query.ToString());

            query.Query.Accept(new MyVisitor());
        }
    }
}

This is where the meat of the question lies. As you can see I've identified a few things that need to be included, but I don't have a clue how to put these things together.

public class MyVisitor : BasicExpressionVisitor
{
    public override void Visit(DbFilterExpression expression)
    {
        // add WHERE [IsActive] = 1
        /* Building blocks:
         *      DbExpressionBuilder.Equal
         *      DbExpressionBuilder.True
         *      DbExpressionBuilder.And   --- only when a filter expression already exists
         */

        var isActiveProperty = expression.Property("IsActive");
        var equalExp = DbExpressionBuilder.Equal(isActiveProperty, DbExpressionBuilder.True);
    }
}

Supposing we had this:

class Program
{
    static void Main(string[] args)
    {
        using (var ctx = new MyDbContext())
        {
            var entities = ctx.Entities.FirstOrDefault(x => x.Name == "amy");
            Console.WriteLine(entities);
        }
    }
}

This query results in this command tree:

DbQueryCommandTree
|_Parameters
|_Query : Collection{Record['Id'=Edm.Int32, 'Name'=Edm.String, 'IsActive'=Edm.Boolean]}
  |_Project
    |_Input : 'Limit1'
    | |_Limit
    |   |_Filter
    |   | |_Input : 'Extent1'
    |   | | |_Scan : CodeFirstDatabase.MyEntity
    |   | |_Predicate
    |   |   |_
    |   |     |_'amy'
    |   |     |_=
    |   |     |_Var(Extent1).Name
    |   |_1
    |_Projection
      |_NewInstance : Record['Id'=Edm.Int32, 'Name'=Edm.String, 'IsActive'=Edm.Boolean]
        |_Column : 'Id'
        | |_Var(Limit1).Id
        |_Column : 'Name'
        | |_Var(Limit1).Name
        |_Column : 'IsActive'
          |_Var(Limit1).IsActive

But I don't understand where to go from here.

1
8
3/31/2015 8:00:00 PM

Popular Answer

I used the following references to help me implement a custom "soft delete" interception mechanism :

Hope this will help

1
5/23/2017 12:17:31 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow