2015-03-31 28 views
5

Questo è puramente un esperimento di apprendimento (yay scienza!). Questo non è pensato per essere effettivamente utilizzato ovunque. Voglio imparare come funzionano gli intercettori dell'albero dei comandi di EF6.Learning Entity Framework 6 interceptor dell'albero di comando

Sto cercando di modificare l'albero dei comandi intercettato per aggiungere un filtro "IsActive = 1" a tutte le query. Ho notato una grave carenza di documentazione su questo genere di cose. Due domande:

Come intercettare selettivamente gli alberi di comando per dire, entità che implementano un'interfaccia (come IHasAnActiveProperty)? Al momento noto che l'intercettore intercetta le query per il contesto della cronologia, che non ha nulla a che fare con il mio MyEntity.

Come si aggiunge il filtro a tutte le query?

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()); 
     } 
    } 
} 

Qui si trova la carne della domanda. Come puoi vedere ho identificato alcune cose che devono essere incluse, ma non ho idea di come mettere insieme queste cose.

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); 
    } 
} 

Supponendo che abbiamo avuto questo:

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

risultati di questa interrogazione in questo albero di comando:

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 

Ma non capisco dove andare da qui.

+1

'ExpressionVisitor' non è stato progettato per modificare l'espressione, ma per conoscerne l'esistenza e/o registrarlo. Se vuoi modificare il comando dovrai derrare da 'IDbCommandInterceptor'. –

+0

@ErikPhilips, che spiega * tanto *. – Amy

+0

@Amy Quindi hai mai ricevuto una versione funzionante del tuo codice? Sarei interessato a imparare da esso. – Terry

risposta

1

ho usato i seguenti riferimenti per aiutarmi a implementare un custom "soft delete" meccanismo di intercettazione:

Spero che ciò possa essere d'aiuto