Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Cached ExecuteQuery
Message
De
02/11/2008 09:26:57
 
 
À
Tous
Information générale
Forum:
ASP.NET
Catégorie:
LINQ
Titre:
Cached ExecuteQuery
Versions des environnements
Environment:
C# 3.0
OS:
Vista
Network:
Windows 2008 Server
Database:
MS SQL Server
Divers
Thread ID:
01358958
Message ID:
01358958
Vues:
62
I implemented cached DLinq ExecuteQuery method.
However some queries are run against database always because keys
are not found in cache.

Maybe equality comparer or other parts of implementation are wrong and/or
inefficient.

How to fix this code ?
Which is best way to create static ExecuteQuery method which caches all
queries during
application lifetime ?
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

class DLinqCache
{

    class Key
    {
        /// <summary>
        /// Sql command text possibly containing {n} parameters
        /// </summary>
        internal string CommandText;

        /// <summary>
        /// Command parameter values: scalar types present in sql server
types like int, int?, decimal, decimal?, string, DateTime, DateTime?,
        /// float, bool, bool?, double.
        /// </summary>
        internal object[] Parameters;

        /// <summary>
        /// Entity types from which this query depends
        /// </summary>
        internal Type[] SourceTables;
    }

    static Dictionary<Key, object> cache;

    /// <summary>
    /// Main entry point for all cached non-linq queries.
    /// Remember query in cache.
    /// </summary>
    /// <param name="source">types whose or whose child types query is
depending.
    /// Spectial values:
    /// null - volatile. query is not cached
    /// empty array - permanent. cache is cleared only on company cahnge or
re-login or windws clear command.
    /// </param>
    public static IEnumerable<TEntity> ExecuteQuery<TEntity>(string command,
Type[] src, params object[] prm)
        where TEntity : new()
    {
        // todo: implement weak reference cache?
        var key = new Key { SourceTables = src, CommandText = command,
Parameters = prm };
        if (cache != null)
        {
            if (src != null)
            {
                object res;
                if (cache.TryGetValue(key, out res))
                    return (IEnumerable<TEntity>)res;
            }
        }
        else
        {
            cache = new Dictionary<Key, object>(new KeyComparer());
        }

        using (var db = new Database())
        {
            IEnumerable<TEntity> tul = db.ExecuteQuery<TEntity>(command,
prm);
            cache.Add(key, tul);
            return tul;
        }
    }


static DataChanged( Type entity ) {
           foreach (var k in cache.Where(k =>
IsSubclassOf(k.Key.SourceTables, entity)))
                  cache.Remove(k.Key);
}


    class KeyComparer : IEqualityComparer<Key>
    {
        public bool Equals(Key x, Key y)
        {
            if (x.CommandText != y.CommandText)
                return false;
            if (x.SourceTables.Length != y.SourceTables.Length ||
                x.Parameters.Length != y.Parameters.Length)
                return false;

            for (int i = 0; i < x.SourceTables.Length; i++)
                if (x.SourceTables[i] != y.SourceTables[i])
                    return false;

            for (int i = 0; i < x.Parameters.Length; i++)
                if (x.Parameters[i].ToString() !=
y.Parameters[i].ToString())
                    return false;
            return true;
        }

        public int GetHashCode(Key obj)
        {
            return obj.GetHashCode();
        }
    }

    static bool IsSubclassOf(Type child, Type parent)
    {
        return child == parent || child.IsSubclassOf(parent);
    }

    static bool IsSubclassOf(Type[] childs, Type parent)
    {
        return childs.Any(c => IsSubclassOf(c, parent));
    }
}
Andrus
Répondre
Fil
Voir

Click here to load this message in the networking platform