Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is the "information" that dapper caches?

Tags:

c#

caching

dapper

On Dapper's documentation found here it states:

Limitations and caveats

Dapper caches information about every query it runs, this allow it to materialize objects quickly and process parameters quickly. The current implementation caches this information in a ConcurrentDictionary object.

What exactly does this mean? Ex: Is it caching returned data, or the query itself, or bits of both?

It also says that "this [cached] data is never flushed". How does this effect the "cached information" if the design schema of the table(s) you are querying is changed?

like image 884
JCisar Avatar asked Mar 27 '12 21:03

JCisar


1 Answers

As far as I know has each query you issue an Identity, depending on the sql query, its command type and its parameters. The cache is a dictionary with concurrent access.

Dictionary<Identity, CacheInfo> _queryCache

This CacheInfo object contains the IDataReader and IDBCommand functions and some control counters which limit the cached amount.

Since no server-side (database schema etc.) are cached, it actually doesn't have any influence.

Edit: Thats how the Identity class looks like used for caching.

private Identity(string sql, CommandType? commandType, string connectionString, Type type, Type parametersType, Type[] otherTypes, int gridIndex)
        {
            this.sql = sql;
            this.commandType = commandType;
            this.connectionString = connectionString;
            this.type = type;
            this.parametersType = parametersType;
            this.gridIndex = gridIndex;
            unchecked
            {
                hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this
                hashCode = hashCode * 23 + commandType.GetHashCode();
                hashCode = hashCode * 23 + gridIndex.GetHashCode();
                hashCode = hashCode * 23 + (sql == null ? 0 : sql.GetHashCode());
                hashCode = hashCode * 23 + (type == null ? 0 : type.GetHashCode());
                if (otherTypes != null)
                {
                    foreach (var t in otherTypes)
                    {
                        hashCode = hashCode * 23 + (t == null ? 0 : t.GetHashCode());
                    }
                }
                hashCode = hashCode * 23 + (connectionString == null ? 0 : connectionString.GetHashCode());
                hashCode = hashCode * 23 + (parametersType == null ? 0 : parametersType.GetHashCode());
            }
        }

And here's the CacheInfo

class CacheInfo

        {
            public Func<IDataReader, object> Deserializer { get; set; }
            public Func<IDataReader, object>[] OtherDeserializers { get; set; }
            public Action<IDbCommand, object> ParamReader { get; set; }
            private int hitCount;
            public int GetHitCount() { return Interlocked.CompareExchange(ref hitCount, 0, 0); }
            public void RecordHit() { Interlocked.Increment(ref hitCount); }
        }

And finally the container of the cache.

static readonly System.Collections.Concurrent.ConcurrentDictionary<Identity, CacheInfo> _queryCache = new System.Collections.Concurrent.ConcurrentDictionary<Identity, CacheInfo>();

Have a look at the source code, its very well written and easy to follow / debug. Just drag the file into your project.

like image 178
Alex Avatar answered Nov 15 '22 17:11

Alex