当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Learning Entity Framework 6 command tree interceptors

问题描述:

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.

网友答案:

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

  • Entity Framework: Building Applications with Entity Framework 6 (as far as I remember, the part about interceptors is around min 20 with a focus on the SCAN node which should answer your question)
  • How can I suppress execution from an Entity Framework 6 IDbCommandTreeInterceptor?
  • Missing EF Feature Workarounds: Filters (with an interesting point about query caching issues in the comments)

Hope this will help

分享给朋友:
您可能感兴趣的文章:
随机阅读: