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.
"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'. –
@ErikPhilips, to wyjaśnia * tak bardzo *. – Amy
@Amy Czy otrzymałeś działającą wersję swojego kodu? Byłbym zainteresowany, aby się z tego wyciągnąć. – Terry