Вопрос

I am just doing some experiments on Castle AR and 2nd level cache of NH. In the following two methods, I can see caching working fine but only for the repetition of the call of each. In other words if I call RetrieveByPrimaryKey twice for same PK, the object is found in cache. And if I call RetrieveAll twice, I see SQL issued only once.

But if I call RetrieveAll and then RetrieveByPrimaryKey with some PK, I see two SQL statements getting issued. My question is, Why AR does not look for that entity in cache first? Sure it would have found it there as a result of previous call to RetrieveAll.

    public static T RetrieveByPrimaryKey(Guid id)
    {
        var res = default(T);
        var findCriteria = DetachedCriteria.For<T>().SetCacheable(true);
        var eqExpression = NHibernate.Criterion.Expression.Eq("Id", id);
        findCriteria.Add(eqExpression);
        var items = FindAll(findCriteria);
        if (items != null && items.Length > 0)
            res = items[0];
        return res;
    }

    public static T[] RetrieveAll()
    {
        var findCriteria = DetachedCriteria.For<T>().SetCacheable(true);
        var res = FindAll(findCriteria);
        return res;
    }
Это было полезно?

Решение

You're using caching on specific queries. that means that cache lookup is done in the following way:
search the cahce for results of a query with identical syntax AND the same parameters. If found- use cached results.

nHibernate (this has nothing to do with AR, by the way) doesn't know that logically, one query 'contains' the other. so this is why you're getting 2 db trips.

I would suggest using ISession.Get to retreive items by ID (it's the recommended method). I think (not tested it though) that Get can use items cached by other queries.
here's a nice blog post from ayende about it.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top