2015-03-31 66 views
5

To jest czysto eksperymentu uczenia (yay nauki!). To nie ma być faktycznie używane w dowolnym miejscu. Chcę się dowiedzieć, jak działają przechwytywacze drzewa poleceń EF6.Nauka Entity Framework 6 command przechwytywacze drzewo

Próbuję zmodyfikować przechwycone drzewo poleceń, aby dodać filtr "IsActive = 1" do wszystkich zapytań. Zauważyłem poważne braki w dokumentacji tego typu rzeczy. Dwa pytania:

Jak selektywnie przechwytywać drzewa poleceń, np. Jednostki, które implementują interfejs (np. IHasAnActiveProperty)? W tej chwili zauważam, że przechwytujący przechwytuje zapytania w kontekście historii, co nie ma nic wspólnego z moim MyEntity.

Jak dodać filtr do wszystkich zapytań?

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

Tu tkwi mięso. Jak widać, udało mi się zidentyfikować kilka rzeczy, które należy uwzględnić, ale nie mam pojęcia, jak połączyć te rzeczy.

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

Przypuśćmy mieliśmy to:

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

Wyniki Ten zapytań w tym drzewie poleceń:

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 

Ale nie rozumiem, gdzie iść stąd.

+1

"Wyrażenie Expression" nie zostało zaprojektowane do modyfikowania wyrażenia, ale do poznania jego istnienia i/lub zarejestrowania go. Jeśli chcesz zmodyfikować polecenie, będziesz musiał wykreślić z 'IDbCommandInterceptor'. –

+0

@ErikPhilips, to wyjaśnia * tak bardzo *. – Amy

+0

@Amy Czy otrzymałeś działającą wersję swojego kodu? Byłbym zainteresowany, aby się z tego wyciągnąć. – Terry

Odpowiedz

1

użyłem następujących odniesień mi pomóc wdrożyć zwyczaj „miękkie usuwać” mechanizm przechwytywania:

Mam nadzieję, że to pomoże