Caching DLinq ExecuteQuery results

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrus

    Caching DLinq ExecuteQuery results

    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 ?

    Andrus.


    using System;
    using System.Collecti ons.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, objectcache;

    /// <summary>
    /// Main entry point for all cached non-linq queries.
    /// Remember query in cache.
    /// </summary>
    /// <param name="source">t ypes 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<TEn tityExecuteQuer y<TEntity>(stri ng 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.TryGetVa lue(key, out res))
    return (IEnumerable<TE ntity>)res;
    }
    }
    else
    {
    cache = new Dictionary<Key, object>(new KeyComparer());
    }

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


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


    class KeyComparer : IEqualityCompar er<Key>
    {
    public bool Equals(Key x, Key y)
    {
    if (x.CommandText != y.CommandText)
    return false;
    if (x.SourceTables .Length != y.SourceTables. Length ||
    x.Parameters.Le ngth != y.Parameters.Le ngth)
    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.Le ngth; 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(Ty pe child, Type parent)
    {
    return child == parent || child.IsSubclas sOf(parent);
    }

    static bool IsSubclassOf(Ty pe[] childs, Type parent)
    {
    return childs.Any(c =IsSubclassOf(c , parent));
    }
    }

Working...