EF6 Disable Query Plan Caching with Command Tree Interceptor

后端 未结 4 1970
执笔经年
执笔经年 2021-02-18 14:28

I\'m using IDbCommandTreeInterceptor to implement soft-delete functionality. Inside standard TreeCreated method I check whether given query command con

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-18 14:54

    Are you sure that you problem happens in all queries? In your example you have used the Find(), what if you use ToList()? The problem doesn't happen, right?

    For testing purposes, try using Where method instead of Find(), I believe that you won't have problems...

    If the above theory is true, replace the Find() by Where inside a some kind of repository class. Then you don't need to change anything else in your code.

    For example, in your repository class:

    public YourClass Find(id)
    {
        //do not use Find here 
        return context.FirstOrDefault(i => i.Id == id); //or Where(i => i.Id == id).FirstOrDefault();
    }
    

    In your business logic:

    var user = repository.Find(id);
    

    The Find() method documentation https://msdn.microsoft.com/en-us/library/system.data.entity.dbset.find%28v=vs.113%29.aspx says:

    "...if an entity with the given primary key values exists in the context, then it is returned immediately without making a request to the store..."

    So, I believe that the problem is the Find(). Using a repository pattern, replacing Find by Where, is the easiest workaround that I can imagine right now. Or else, instead of replace, you can check if the softdelete is activated, and then choose your preferred method. What do you think about that?

    A more difficult approach is creating a class that inherits from DbSet and override the Find(), which will be too complicated.

    EDIT

    To help us see what is happening, create a console application and log the database operation, like this:

    using (var context = new BlogContext()) 
    { 
        context.Database.Log = Console.Write; 
    
        // Your code here... 
        // Call your query twice, with and without softdelete
    }
    

    Paste the log, then we'll see for sure if the sql is incorrect or the data is being cached.

    EDIT 2

    Ok... instead of adding the interceptor in the constructor of the configuration class, add it in the constructor of the context, like this:

    //the dbcontext class      
    
     private IDbCommandTreeInterceptor softDeleteInterceptor;
     public DataContext()
           : base("YourConnection")
     {
        //add the interceptor 
        softDeleteInterceptor = new SoftDeleteInterceptor()           
          DbInterception.Add(softDeleteInterceptor);
     }
    

    Then, inside your context class, create a method that removes the interceptor, like this:

    public void DisableSoftDelete() 
    {
         DbInterception.Remove(softDeleteInterceptor);
    }
    

    Call the method above when you want to disable the softdelete, context.DisableSoftDelete();

提交回复
热议问题