I'm writing a management intelligence application which requires quite a lot of complex database querying with some queries being quite expensive. To aid performance I'm using Memcached quite heavily to store as much as I can in memory.
This has led to quite a lot of duplication in my code which I'm eager to get rid of and build a cleaner data access solution. Quite a lot of my data access functions have ended up looking like this..
public int NumberOfTimeouts(DateTime date, int? applicationId)
{
var functionCacheKey = "NumberOfTimeouts";
var cacheKey = string.Format("{0}-{1}-{2}-{3}", RepositoryCacheKey, functionCacheKey, date, applicationId);
var cachedNumberTimeouts = _cache.Retrieve(cacheKey);
if (cachedNumberTimeouts != null)
{
return (int)cachedNumberTimeouts;
}
//query logic here, calculates numberOfTimeouts
UpdateCache(date, cacheKey, numberOfTimeouts);
return numberOfTimeouts;
}
I'm just not too sure what the standard approach is to this, could it involve using a custom attribute class or something similar?
This is a cross-cutting concern. The Decorator pattern may be applicable here. I may be inexperienced in this pattern, however I will give it a shot
// model
public class CustomObject
{
public int Id { get; set; }
}
// interface
public interface IRepository<T>
{
IEnumerable<T> Find(Expression<Func<T, bool>> expression);
}
public interface ICacheableRepository<T>
{
IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey);
}
public interface IRepositoryCacheManager<T>
{
IEnumerable<T> Get(int key);
bool Any(int key);
void Add(int key, IEnumerable<T> result);
}
// cache manager
public class RepositoryCacheManager<T> : IRepositoryCacheManager<T>
{
private Dictionary<int, IEnumerable<T>> cache = new Dictionary<int,IEnumerable<T>>();
#region IRepositoryCache<T> Members
public IEnumerable<T> Get(int key)
{
return cache[key];
}
public bool Any(int key)
{
IEnumerable<T> result = null;
return cache.TryGetValue(key, out result);
}
public void Add(int key, IEnumerable<T> result)
{
cache.Add(key, result);
}
#endregion
}
// cache repository decorator
public class CachedRepositoryDecorator<T> : IRepository<T>, ICacheableRepository<T>
{
public CachedRepositoryDecorator(IRepositoryCacheManager<T> cache
, IRepository<T> member)
{
this.member = member;
this.cache = cache;
}
private IRepository<T> member;
private IRepositoryCacheManager<T> cache;
#region IRepository<T> Members
// this is not caching
public IEnumerable<T> Find(Expression<Func<T, bool>> expression)
{
return member.Find(expression);
}
#endregion
#region ICacheableRepository<T> Members
public IEnumerable<T> Find(Expression<Func<T, bool>> expression, Func<int> cacheKey)
{
if (cache.Any(cacheKey()))
{
return cache.Get(cacheKey());
}
else
{
IEnumerable<T> result = member.Find(expression);
cache.Add(cacheKey(), result);
return result;
}
}
#endregion
}
// object repository
public class CustomObjectRepository : IRepository<CustomObject>
{
#region IRepository<CustomObject> Members
public IEnumerable<CustomObject> Find(Expression<Func<CustomObject, bool>> expression)
{
List<CustomObject> cust = new List<CustomObject>();
// retrieve data here
return cust;
}
#endregion
}
// example
public class Consumer
{
// this cache manager should be persistent, maybe can be used in static, etc
IRepositoryCacheManager<CustomObject> cache = new RepositoryCacheManager<CustomObject>();
public Consumer()
{
int id = 25;
ICacheableRepository<CustomObject> customObjectRepository =
new CachedRepositoryDecorator<CustomObject>(
cache
, new CustomObjectRepository()
);
customObjectRepository.Find(k => k.Id == id, () => { return id; });
}
}
Please note:
I haven't tested this code, don't know whether it is fully functional or not. I just describe the illustration
Yes, this has code smell by having the ICacheableRepository overloading for Find, however I am incapable in using Expression as Key in Dictionary
The pros:
This CachedRepositoryDecorator can be used to ANY generic repository (reusable)
No caching logic inside the select process, emphasize SRP
The cons:
Hard to implement without ORM, maybe you will need some tweaks with reflection to make it works without ORM
Hard to understand at beginning
Hard to wire without DI Container
Credit to this article :)
I think the Unit of Work pattern is what you need.
More info:
http://martinfowler.com/eaaCatalog/unitOfWork.html
http://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern
http://msdn.microsoft.com/en-us/magazine/dd882510.aspx
Or a framework that contains the UoW pattern: https://github.com/riteshrao/ncommon
Related
Suppose (entirely hypothetically ;) ) that I have nuget package, which essentially exposes a set of static extension methods:
public static class MyNugetLibrary
{
public static int DoSomethingExpensiveAndUseful(this string input)
{
return input.Length;
}
public static int DoSomethingElseExpensiveAndUseful(this string input)
{
return (int)input.ToCharArray().First();
}
}
And, for sane reasons, I conclude that what this package really needs is caching. The output is constant given the input, and the input is something primitive.
In my case there's no conceivable way for the output to change, so I never have to worry about cache invalidation etc.
If there were just 1 or 2 methods I could just add a private static Dictionary to the extension class, and in the method ask the dictionary for the answer.
But I'd quite like to not duplicate so much code, and there's a really nice memoize function:
public static Func<T, TResult> Memoize<T, TResult>(this Func<T, TResult> f)
{
var cache = new ConcurrentDictionary<T, TResult>();
return a => cache.GetOrAdd(a, f);
}
(Stolen from here: https://www.aleksandar.io/post/memoization/)
But I can't quite figure out how to use that method to make these functions memoized, without changing the external interface of my package.
How can I do this?
Massive bonus points available if we can further do this in such a way that the caching can be disabled by the end user (MyNugetLibrary.DisableCaching()) in case they are worried about, e.g. the memory footprint.
You can use Fody/MethodCache
Run
Install-Package Fody
Install-Package MethodCache.Fody
Then you can change your methods to:
public interface ICache
{
bool Contains(string key);
T Retrieve<T>(string key);
void Store(string key, object data);
void Remove(string key);
}
public static class MyNugetLibrary
{
public static ICache Cache { get; set; } = DefaultCache;
public readonly static ICache DefaultCache = new MemoryCache();
public readonly static ICache NoCache = new UnCache();
[Cache]
public static int DoSomethingExpensiveAndUseful(this string input)
{
return input.Length;
}
[Cache]
public static int DoSomethingElseExpensiveAndUseful(this string input)
{
return (int)input.ToCharArray().First();
}
}
I have a data access class that acts as an intermediary between logic classes and the underlying datasource, which is interchangeable. This class allows you to query the datasource using lambdas, LINQ-style. A source-agnostic class provides high-level functionality powered by a few basic operations (Add, GetAll, Update, Delete, Commit) that are implemented by small adapter classes, one for each source type (SQL, SQlite, XML serialiser, WCF client, REST client, whatever).
My problem is that some relational data sources (particularly SQLite) aren't smart enough to load relationship properties when I need them; I have to explicitly ask for them to be included. This is fine for my Get methods; I can pass a params array of expressions to load anything I need. With .Any(), however, this feels a bit odd - if I'm asking if there are any Customer records whose Purchases list contains a certain item, I shouldn't then have to tell it to load the Purchases list; that seems like the sort of thing it should be able to figure out.
So my Any() method takes Expression<Func<T, bool>> where T is obviously going to be the type I'm operating on. In the above example, it'd be used something like this:
using (var db = _dataAccessProvider.NewTransaction())
{
return db.Any<Customer>(c => c.Purchases.Contains(someProduct));
}
Is it possible to take the Expression<Func<Customer, bool>> that represents the operation c => c.Purchases.Contains(someProduct)) and work out that the property it's referring to is c => c.Purchases? How would I go about doing that? What about a lambda that touches multiple properties?
Use ExpressionVisitor to find all MemberExpression expressions which reference required object properties.
Quick example:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
class Program
{
sealed class ReferencedPropertyFinder : ExpressionVisitor
{
private readonly Type _ownerType;
private readonly List<PropertyInfo> _properties = new List<PropertyInfo>();
public ReferencedPropertyFinder(Type ownerType)
{
_ownerType = ownerType;
}
public IReadOnlyList<PropertyInfo> Properties
{
get { return _properties; }
}
protected override Expression VisitMember(MemberExpression node)
{
var propertyInfo = node.Member as PropertyInfo;
if(propertyInfo != null && _ownerType.IsAssignableFrom(propertyInfo.DeclaringType))
{
// probably more filtering required
_properties.Add(propertyInfo);
}
return base.VisitMember(node);
}
}
private static IReadOnlyList<PropertyInfo> GetReferencedProperties<T, U>(Expression<Func<T, U>> expression)
{
var v = new ReferencedPropertyFinder(typeof(T));
v.Visit(expression);
return v.Properties;
}
sealed class TestEntity
{
public int PropertyA { get; set; }
public int PropertyB { get; set; }
public int PropertyC { get; set; }
}
static void Main(string[] args)
{
Expression<Func<TestEntity, int>> expression =
e => e.PropertyA + e.PropertyB;
foreach(var property in GetReferencedProperties(expression))
{
Console.WriteLine(property.Name);
}
}
}
Can someone help me figure out how to implement this method generically? The compiler complains that it cannot resolve t.Id. Which makes sense but, how do I tell it that all objects that pass will have an Id property. Here is the interface I defined for T:
namespace LiveWire.Model
{
public interface ILiveWireModel
{
Guid Id { get; }
}
}
The interface for all repositories:
internal interface ILiveWireRepository<T>
{
ICacheProvider Cache { get; }
string CacheKey { get; }
SqlConnection CreateConnection();
IEnumerable<T> GetData<TD>();
IEnumerable<T> LoadData<TD>();
Dictionary<Guid, T> GetCachedData<TD>();
void ClearCache();
}
And my method:
public IEnumerable<T> GetData<TD>()
where TD : ILiveWireModel
{
var data = GetCachedData<TD>();
if (data == null)
{
data = LoadData<TD>().ToDictionary(t => t.Id);
if (data.Any())
{
Cache.Set(CacheKey, data, 30);
}
}
return data.Values;
}
I'm including the whole class here which I hope will clear some things up.
internal abstract class LiveWireRepositoryBase<T> : ILiveWireRepository<T>
{
public ICacheProvider Cache { get; private set; }
public string CacheKey { get; private set; }
internal LiveWireRepositoryBase()
{
Cache = new DefaultCacheProvider();
}
public SqlConnection CreateConnection()
{
return new SqlConnection(
ConfigurationManager
.ConnectionStrings["LiveWire4Database"]
.ConnectionString);
}
public IEnumerable<T> GetData<TD>()
where TD : ILiveWireModel
{
var data = GetCachedData<TD>();
if (data == null)
{
data = LoadData<TD>().ToDictionary(t => t.Id);
if (data.Any())
{
Cache.Set(CacheKey, data, 30);
}
}
return data.Values;
}
public IEnumerable<T> LoadData<TD>()
{
return new List<T>();
}
public Dictionary<Guid, T> GetCachedData<TD>()
{
throw new NotImplementedException();
}
public void ClearCache()
{
throw new NotImplementedException();
}
}
I'm getting this error which I don't understand. I tried using an explicit interface implementation but, that wound up making me remove my where constraint.
The constraints for type parameter 'TD' of method 'LiveWire.Data.Repositories.LiveWireRepositoryBase.GetData()' must match the constraints for type parameter 'TD' of interface method 'LiveWire.Data.Repositories.ILiveWireRepository.GetData()'. Consider using an explicit interface implementation instead. C:\projects\LiveWire\Solution\LiveWire.Data\Repositories\LiveWireRepositoryBase.cs 32 31 LiveWire.Data
You'll be able to make this method compile by changing the class's signature to
public sealed class MyCache<T> where T : ILiveWireModel
(or, if the class is in a different namespace, where T : LiveWire.Model.ILiveWireModel).
That said, I'm not sure that this change will solve your problem. I have only seen a few snippets of your project's code, so I may be wrong, and take the following with a grain of salt:
Is it really the best design to keep GUID-keyed and integer-keyed values in the same cache? Presumably, you're taking data from two different sources, one which uses GUID keys and one which uses integer keys. But in the future, what if you add a third source, which also uses integer keys? The keys from the two integer-key sources could clash, and your cache would always be wrong for some queries. Personally, I'd maintain a second table or function (maybe keep a table of mappings for integer-valued keys, just pass through the GUID-valued keys) somewhere that knows the mapping from objects to keys, and use that function whenever I need to check if an object is cached. All the rest of the time, then, your cache could work directly in terms of keys and values, and not have to mess with different types of keys.
The exception you get at this stage just says that the interface definition
IEnumerable<T> GetData<TD>();
hasn't got the same constraints (i.e. the where) for the type parameter TD as the implementation
public IEnumerable<T> GetData<TD>() where TD : ILiveWireModel
You need to put the same constraint in the interface.
public IEnumerable<T> GetData<T>() where T:LiveWire.Model.ILiveWireModel {
//.../
}
Specialization of generics.
You need to fix the declaration first
public IEnumerable<T> GetData<T>()
then, in order to know what you can use ON T, you have to tell it what T is allowed to be.
public IEnumerable<T> GetData<T>() where T : ILiveWireModel
Finally, you haven't told us what var data actually contains, that would be inside of the GetCachedData and the LoadData Functions, which you dont pass T into and we dont have any idea what it returns.
I would expect to see something like this though
public IEnumerable<T> GetData<T>() where T : ILiveWireModel
{
var data = GetCachedData<T>();
if (data == null)
{
data = LoadData<T>().ToDictionary(t => t.Id);
if (data.Any())
{
Cache.Set(CacheKey, data, 30);
}
}
return data.Values;
}
I got bored with writing same to code again and again to cache the objects in data access layer.
Is there anyway to cache c# function results without much changes to functions.
Is there any framework supports this functionality at the moment?
Can i archive the same by writing custom "c# function attributes"? if so, drop me some points to start implementation?
Possibility 1: Use IL Weaving
Postsharp was mentioned before.
You could also try the MethodCache.Fody package.
Possibility 2: Use an Proxy / Interception Framework
Example (Ninject & Ninject.Interception):
public class CacheAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<CachingInterceptor>();
}
}
public class CachingInterceptor : IInterceptor
{
private ICache Cache { get; set; }
public CachingInterceptor(ICache cache)
{
Cache = cache;
}
public void Intercept(IInvocation invocation)
{
string className = invocation.Request.Target.GetType().FullName;
string methodName = invocation.Request.Method.Name;
object[] arguments = invocation.Request.Arguments;
StringBuilder builder = new StringBuilder(100);
builder.Append(className);
builder.Append(".");
builder.Append(methodName);
arguments.ToList().ForEach(x =>
{
builder.Append("_");
builder.Append(x);
});
string cacheKey = builder.ToString();
object retrieve = Cache.Retrieve<object>(cacheKey);
if (retrieve == null)
{
invocation.Proceed();
retrieve = invocation.ReturnValue;
Cache.Store(cacheKey, retrieve);
}
else
{
invocation.ReturnValue = retrieve;
}
}
}
Then you could decorate functions like this:
[Cache]
public virtual Customer GetCustomerByID(int customerID)
{
return CustomerRepository.GetCustomerByID(customerID);
}
Intercepted functions have to be virtual and classes must be created by the Ninject kernel. If you rely on performance, you could proxy classes directly via Castle.DynamicProxy (which is internally used by Ninject.Extensions.Interception.DynamicProxy).
Possibility 3: Use an Expression wrapper
You could pass the function as expression, generate a caching key containing class, method and parameter information and invoke the expression if not found in your Cache. This adds more runtime overhead than AOP / Proxy frameworks, but will be sufficient for simple solutions.
private T CacheAction<T>(Expression<Func<T>> action, [CallerMemberName] string memberName = "") where T : class
{
MethodCallExpression body = (MethodCallExpression)action.Body;
ICollection<object> parameters = new List<object>();
foreach (MemberExpression expression in body.Arguments)
{
parameters.Add(((FieldInfo)expression.Member).GetValue(((ConstantExpression)expression.Expression).Value));
}
StringBuilder builder = new StringBuilder(100);
builder.Append(GetType().FullName);
builder.Append(".");
builder.Append(memberName);
parameters.ToList().ForEach(x =>
{
builder.Append("_");
builder.Append(x);
});
string cacheKey = builder.ToString();
T retrieve = Cache.Retrieve<T>(cacheKey);
if (retrieve == null)
{
retrieve = action.Compile().Invoke();
Cache.Store(cacheKey, retrieve);
}
return retrieve;
}
public Customer GetCustomerByID(int customerID)
{
return CacheAction(() => CustomerRepository.GetCustomerByID(customerID));
}
You can create caching attributes with PostSharp. You can use the Cache attribute.
If I read you question correct, the right term for what you want is memoization. Wikipedia gives more details on this subjects. Unfortunately there is no reference to a C# library supporting it.
Lazy store it's value after first run.
Example: http://msdn.microsoft.com/en-us/vstudio/bb870976
I use this simple implementation of the System.Runetime.Caching namespace:
public class InMemoryCache : ICacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
{
T item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddHours(4));
}
return item;
}
public void Clear(string cacheKey)
{
MemoryCache.Default.Remove(cacheKey);
}
}
interface ICacheService
{
T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
void Clear(string cacheKey);
}
Can be used in the following manner:
var cacheProvider = new InMemoryCache();
var cachedResult = cacheProvider.GetOrSet("YourCacheKey",
() => MethodToCache());
First call to the method will cache the result, the next call will return the cached result.
The Cache Application block is Microsoft's answer to built in library for Caching in .NET.
I suggest Spring.Net AOP.
It basically creates a proxy and the calls can be redirected from/to the cache.
http://www.springframework.net/doc/reference/html/aop-quickstart.html
and then you can have something like that for your advice:
public class CachingAroundAdvice : IMethodInterceptor
{
#region Variable Declarations
private Priority priority = Priority.Normal;
#endregion
public object Invoke(IMethodInvocation invocation)
{
// declare local variables
string cacheKey = string.Empty;
object dataObject = null;
// build cache key with some algorithm
cacheKey = CreateCacheKey(invocation.Method, invocation.Arguments);
// retrieve item from cache
dataObject = CacheManager.Cache.GetData(cacheKey);
// if the dataobject is not in cache proceed to retrieve it
if (null == dataObject)
{
dataObject = invocation.Proceed();
// add item to cache
CacheManager.Cache.Add(cacheKey, dataObject, CachePriority, null, Expiration);
}
// return data object
return dataObject;
}
You could use a Dictionary to cache the function. A dictionary maps keys to values and a function maps arguments to values. So conceptually, a dictionary fits as a cache for a function. Here's a simple class to do that:
/// <summary>
/// The lazy function map caches the results of calls to the backing function. Every time the function is called on an argument u and returns v,
/// the pair (u, v) is stored in the dictionary.
/// </summary>
class LazyFunctionMapImpl<T, U> : ILazyFunctionMap<T, U>
{
private readonly Dictionary<T, U> _backingDictionary;
private readonly Func<T, U> _backingFunction;
public LazyFunctionMapImpl(Func<T, U> backingFunction)
{
_backingDictionary = new Dictionary<T, U>();
_backingFunction = backingFunction;
}
public U this[T index]
{
get
{
if (_backingDictionary.ContainsKey(index))
{
return _backingDictionary[index];
}
U valueAtIndex = _backingFunction(index);
_backingDictionary.Add(index, valueAtIndex);
return valueAtIndex;
}
}
public void Clear()
{
_backingDictionary.Clear();
}
}
And here's a couple of interfaces to go with it:
/// <summary>
/// A function map that should lazily cache param/result pairs until clear is called.
/// </summary>
public interface ILazyFunctionMap<T, U> : IFunctionMap<T, U>
{
/// <summary>
/// Should invalidate any caches forcing the underyling function to be called afresh
/// </summary>
void Clear();
}
public interface IFunctionMap<T, U>
{
/// <summary>
/// Mapped values representing the underlying function.
/// </summary>
U this[T index] { get; }
}
I'm trying to build a generic class to work with entities from EF. This class talks to repositories, but it's this class that creates the expressions sent to the repositories. Anyway, I'm just trying to implement one virtual method that will act as a base for common querying. Specifically, it will accept a an int and it only needs to perform a query over the primary key of the entity in question.
I've been screwing around with it and I've built a reflection which may or may not work. I say that because I get a NotSupportedException with a message of LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object, System.Object[])' method, and this method cannot be translated into a store expression. So then I tried another approach and it produced the same exception but with the error of The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities. I know it's because EF will not parse the expression the way L2S will.
Anyway, I'm hopping someone with a bit more experience can point me into the right direction on this. I'm posting the entire class with both attempts I've made.
public class Provider<T> where T : class {
protected readonly Repository<T> Repository = null;
private readonly string TEntityName = typeof(T).Name;
[Inject]
public Provider(
Repository<T> Repository) {
this.Repository = Repository;
}
public virtual void Add(
T TEntity) {
this.Repository.Insert(TEntity);
}
public virtual T Get(
int PrimaryKey) {
// The LINQ expression node type 'ArrayIndex' is not supported in
// LINQ to Entities.
return this.Repository.Select(
t =>
(((int)(t as EntityObject).EntityKey.EntityKeyValues[0].Value) == PrimaryKey)).Single();
// LINQ to Entities does not recognize the method
// 'System.Object GetValue(System.Object, System.Object[])' method,
// and this method cannot be translated into a store expression.
return this.Repository.Select(
t =>
(((int)t.GetType().GetProperties().Single(
p =>
(p.Name == (this.TEntityName + "Id"))).GetValue(t, null)) == PrimaryKey)).Single();
}
public virtual IList<T> GetAll() {
return this.Repository.Select().ToList();
}
protected virtual void Save() {
this.Repository.Update();
}
}
UPDATE for #Gabe
This is what my repository class looks like:
public class Repository<T> where T : class {
protected readonly ObjectContext ObjectContext = null;
private readonly IObjectSet<T> ObjectSet = null;
[Inject]
public Repository(
ObjectContext ObjectContext) {
this.ObjectContext = ObjectContext;
this.ObjectSet = this.ObjectContext.CreateObjectSet<T>();
}
public virtual void Delete(
T Entity) {
this.ObjectSet.DeleteObject(Entity);
}
public virtual void Insert(
T Entity) {
this.ObjectSet.AddObject(Entity);
}
public virtual IQueryable<T> Select() {
return this.ObjectSet;
}
public virtual IQueryable<T> Select(
Expression<Func<T, bool>> Selector) {
return this.ObjectSet.Where(Selector);
}
public virtual void Update() {
this.ObjectContext.SaveChanges();
}
}
The names of the methods are based on the SQL functions, not on the LINQ methods, which is where I think you're getting confused on how my repository functions.
As Pauli alludes to, you need to manually create Expression trees, although reflection isn't necessary in this case. Here's how you could write your Get function:
public virtual T Get(
int PrimaryKey)
{
var param = Expression.Parameter(typeof(T));
// create expression for param => param.TEntityNameId == PrimaryKey
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, TEntityName + "Id"),
Expression.Constant(PrimaryKey)),
param);
return this.Repository.Single(lambda);
}
Also, note that your GetAll function doesn't need Select -- return Repository.ToList(); will work just as well.