二级缓存 EF codeFirst 和 Predicate 不适用于 where 子句

Posted

技术标签:

【中文标题】二级缓存 EF codeFirst 和 Predicate 不适用于 where 子句【英文标题】:2nd level caching EF codeFirst and Predicate not working on a where clause 【发布时间】:2014-01-12 21:35:27 【问题描述】:

我有一个关于使用实体框架代码进行缓存的问题。 我需要缓存我的查询结果,我发现了一些我不知道的东西。

Func<T, bool> 谓词在过滤时不起作用,而 Expression<Func<T, bool>> 谓词起作用。

也许我错过了显而易见的事情。

这是我的场景:

每当我调用一个方法时,例如“GetOrders”,我都会在内部使用一个名为“GetCachedModels”的方法来获取缓存版本。

当随后多次调用 “GetOrders(customerNo)”它检查缓存并从那里获取它,如果它在那里。这就是理论。

但是,当使用 Func 谓词时,它找不到项目,但在使用表达式版本时,它会?

我的问题是如何在列表中使用带有 Where 子句的“表达式”? 另一种解决方案是为每个搜索提供一个方法,例如“myservice.GetCustomer(etc..) 或 myservice.GetOrders(etc..) 而不是泛型 我的服务.GetAll();这意味着向接口添加许多方法。

我的代码:

public interface IGenericRepository
    
        IList<T> GetAll<T>() where T : class;
        IList<T> Find<T>(Func<T, bool> predicate) where T : class; //I use this so that I could use the predicate in an where clause against a list.
        etc....

    

在我的存储库中,我有类似的东西:

 public IList<T> Find<T>(Func<T, bool> predicate) where T : class
    
        List<T> models = GetCachedModels<T>().ToList();  
        var result= models.Where(predicate).ToList();  --Does not work!!! tried also with(expression.Compile()).ToList(); !!still no results!!!!
        return result;
    




internal IList<T> GetCachedModels<T>() where T : class
    
        IList<T> models;                
        Type typeParameterType = typeof(T);
        string cacheName = string.Format("0Cache", typeParameterType.Name);
        object cacheView = DbCache.Get(cacheName);
        if (cacheView == null)
        
            models = Set<T>().ToList();
            DbCache.Add(cacheName, models, DateTime.Now.AddHours(1));
        
        else
        
            models = (IList<T>)cacheView;
        
        return models;
    


    //below method works but cannot use cache!!!!

    public IList<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
    
        return Set<T>().Where(predicate).ToList();
    

【问题讨论】:

【参考方案1】:

表达式谓词仅适用于 IQueryable 接口。 List没有继承它,所以如果要使用这个表达式,需要在GetCachedModels方法中返回IQueryable,并返回Set,这样才能查询到这个数据。然后你就可以放置它了。

否则如果你想缓存Set中的所有项目,那么你需要传递Func而不是Expression,然后在Where扩展方法中使用它,像这样-http://dotnetfiddle.net/5YsIy3

【讨论】:

嗨,我使用了 Func 谓词,但没有找到!正如我在我的问题中指出的那样,我觉得这很奇怪。 这是工作示例 - dotnetfiddle.net/aiHR9N。它使用带有硬编码项目的本地列表,因为没有数据库,但它可以工作 您好,感谢您的宝贵时间。我已经尝试从数据库中删除所有数据,然后只留下该行并找到它。但是读取所有数据却没有。发生了一些奇怪的事情。正在调查它....

以上是关于二级缓存 EF codeFirst 和 Predicate 不适用于 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

EF CodeFirst数据注解特性详解

EF实体框架之CodeFirst七

EF实体框架之CodeFirst八

EF-CodeFirst-3搞事

EF-CodeFirst-3搞事

EF5 codefirst 和 SQL CE 的 App.config 设置