6

考虑这种情况。

您有一个允许对其进行某些调用的存储库。这些调用使用 LINQ,并且在返回的数据量方面可能相对昂贵。

鉴于在我的情况下,如果数据是旧的,这并不算太糟糕——可以实现一个缓存,这样就不会在每次调用时都执行大而昂贵的查询。嘿,我们甚至可以实现一些缓存策略来根据时间或使用情况确定何时再次执行该查询。

我想要解决的问题是如何在缓存中键入它。一种方法是简单地说:

"querytype1" = Particular LINQ expression
"querytype2" = Particular LINQ expression

然后通过一个简单的字符串来键入缓存。但是,考虑到我们正在执行 LINQ,我们是否可以通过 LINQ 表达式本身对缓存进行键控?我了解性能指标,但无论如何可以比较两个 LINQ 表达式是否相同?

4

2 回答 2

1

策略:比较 SQL 输出

一种策略可能是检索呈现的 SQL 文本 + 参数,并确定它们是否与来自另一个 IQueryable 的呈现的 SQL + 参数相同。

有关详细信息,请参阅检索 LINQ to sql 语句 (IQueryable) WITH 参数

于 2013-04-18T20:17:58.723 回答
1

这是我目前对此的解决方案。

鉴于此,在存储库中,我们将调用类似于:

public IEnumerable<MYPOCO> GetData(string someParameter, int anotherParameter);

因此我们可以说这些参数是标准。所以,我介绍了一个Criteria类,它基本上包含Dictionary<string, object>实例,并且有一些类型安全的 setter 和 getter,简化了:

public class Criteria
{
    private Dictionary<string, object> _criteria = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

    public Criteria Set<T>(string key, T value)
    {
        _criteria[key] = value;
        return this;
    } // eo Set

    public T Get<T>(string key)
    {
        return _criteria.ContainsKey(key) ? _criteria[key] : default(T);
    } // eo Get

    public Dictionary<string, object> Items { get { return _criteria; } }
}    // eo class Criteria

然后,我写了一个扩展方法Dictionary<TK, TV>,基于这个 Stackoverflow 答案。最后,一个IEqualityComparer<Criteria>适用于Criteria.

这意味着我的缓存现在由标准键入,该标准采用传入存储库的参数进行设置:

public class MyPocoRepository<TMYPOCO>
{
    private Cache<Criteria, IEnumerable<TMYPOCO>> _cache = new Cache<Criteria, IEnumerable<TMYPOCO>>(CriteriaComparer); // is passed to the dictionary constructor which is actually the cache.
    public IEnumerable<TMYPOCO> GetData(string someParameter, int anotherParameter)
    {
        Criteria criteria = new Criteria();
        criteria.Set("someParameter", someParameter)
                .Set("anotherParameter", anotherParameter);
        // we can check the cache now based on this...
    } // eo GetData
} // eo MyPocoRepository<TMYPOCO>

请注意,当我们想要参数完全相同的缓存策略时,这也允许我扩展这个想法,但可能是不同的用户帐户正在访问它(我们可以在条件中添加一个字段,比如用户类型,即使 LINQ 表达式不会使用它)。

于 2013-05-07T19:19:05.230 回答