using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
/// <summary>
/// Find First {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindFirstBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
= returnnew list.Cast<T>().Where(predicate).FirstOrDefaultList<object>();
}
return null;
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindSingleBy<T>Read<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking downList<object> cache.list;
lockif (_cache[typeof_cache.TryGetValue(typeof(T)], out list))
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).SingleOrDefaultFirstOrDefault();
}
return null;
}
return null;
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static boolvoid AddOrUpdate<T>Update<T>(Func<T, bool> predicate, T entity) where T : class
{
// Lets prevent race conditions, locking downList<object> cache.list;
lockif (_cache[typeof_cache.TryGetValue(typeof(T)], out list))
{
// Find Type cache.
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
// Incase this tpye was not pre-loaded into cache we will cache new entities from here on out.
list = new List<object>();
}
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
// If no old record exists no problem we treat this as if its a new record.
if (e != null)
{
// Old record found removing it.
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
// Redis does not care if record is new or old as it will Add or Update regardless.
RedisStore<T>(entity);
return true;
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Remove<T>Delete<T>(T entity) where T : class
{
// Lets prevent race conditions, locking downList<object> cache.list;
lockif (_cache[typeof_cache.TryGetValue(typeof(T)], out list))
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking downList<object> cache.list;
lockif (_cache[typeof_cache.TryGetValue(typeof(T)], out list))
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
return new List<T>();
}
/// <summary>
/// Get Next Sequence for theFind gienAll {T} Entity from Data Store.
/// </summary>
/// <typeparam name="T">class<name="T"></typeparam>
/// <returns>long<<returns>List<T></returns>
public static longList<T> Next<T>All<T>() where T : class
{
return RedisNext<T>RedisGetAll<T>().ToList();
}
#region Redis Commands
//
// Following methods are ment as static private methods.
//
private static List<T> All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
privatepublic static long RedisNext<T>Next<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
/// <summary>
/// Simple Test Entity
/// </summary>
public class User
{
public User()
{
Id = Repository.Next<User>();
}
public long Id { get; private set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
/// <summary>
/// Find First {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindFirstBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindSingleBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).SingleOrDefault();
}
return null;
}
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static bool AddOrUpdate<T>(Func<T, bool> predicate, T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
// Find Type cache.
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
// Incase this tpye was not pre-loaded into cache we will cache new entities from here on out.
list = new List<object>();
}
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
// If no old record exists no problem we treat this as if its a new record.
if (e != null)
{
// Old record found removing it.
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
}
// Redis does not care if record is new or old as it will Add or Update regardless.
RedisStore<T>(entity);
return true;
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Remove<T>(T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
}
/// <summary>
/// Get Next Sequence for the gien {T} Entity from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <returns>long</returns>
public static long Next<T>() where T : class
{
return RedisNext<T>();
}
#region Redis Commands
//
// Following methods are ment as static private methods.
//
private static List<T> All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
private static long RedisNext<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T Read<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static void Update<T>(Func<T, bool> predicate, T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
if (e != null)
{
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Delete<T>(T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
/// <summary>
/// Find All {T}
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>List<T></returns>
public static List<T> All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
#region Redis Commands
public static long Next<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
/// <summary>
/// Simple Test Entity
/// </summary>
public class User
{
public User()
{
Id = Repository.Next<User>();
}
public long Id { get; private set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
List<object>// list;Lets prevent race conditions, locking down cache.
iflock (!_cache.TryGetValue(typeof_cache[typeof(T), out list)])
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
list /// <summary>
/// Find First {T} in object cache.Add
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindFirstBy<T>(entityFunc<T, bool> predicate); where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
= {
List<object> list;
RedisStore<T> if (entity_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T Read<T>FindSingleBy<T>(Func<T, bool> predicate) where T : class
{
List<object>// list;Lets prevent race conditions, locking down cache.
iflock (_cache.TryGetValue(typeof_cache[typeof(T), out list)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefaultSingleOrDefault();
}
return null;
}
return null;
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static voidbool Update<T>AddOrUpdate<T>(Func<T, bool> predicate, T entity) where T : class
{
List<object>// list;Lets prevent race conditions, locking down cache.
iflock (_cache.TryGetValue(typeof_cache[typeof(T), out list)])
{
// Find Type cache.
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
// Incase this tpye was not pre-loaded into cache we will cache new entities from here on out.
list = new List<object>();
}
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
// If no old record exists no problem we treat this as if its a new record.
if (e != null)
{
// Old record found removing it.
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
// Redis does not care if record is new or old as it will Add or Update regardless.
RedisStore<T>(entity);
return true;
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Delete<T>Remove<T>(T entity) where T : class
{
List<object>// list;Lets prevent race conditions, locking down cache.
iflock (_cache.TryGetValue(typeof_cache[typeof(T), out list)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
List<object>// list;Lets prevent race conditions, locking down cache.
iflock (_cache.TryGetValue(typeof_cache[typeof(T), out list)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
return new List<T>();
}
/// <summary>
/// FindGet AllNext Sequence for the gien {T} Entity from Data Store.
/// </summary>
/// <typeparam name="T"><name="T">class</typeparam>
/// <returns>List<T><<returns>long</returns>
public static List<T>long All<T>Next<T>() where T : class
{
return RedisGetAll<T>().ToListRedisNext<T>();
}
#region Redis Commands
//
// Following methods are ment as static private methods.
//
publicprivate static longList<T> Next<T>All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
private static long RedisNext<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
/// <summary>
/// Simple Test Entity
/// </summary>
public class User
{
public User()
{
Id = Repository.Next<User>();
}
public long Id { get; private set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T Read<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static void Update<T>(Func<T, bool> predicate, T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
if (e != null)
{
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Delete<T>(T entity) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
/// <summary>
/// Find All {T}
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>List<T></returns>
public static List<T> All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
#region Redis Commands
public static long Next<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
/// <summary>
/// Simple Test Entity
/// </summary>
public class User
{
public User()
{
Id = Repository.Next<User>();
}
public long Id { get; private set; }
public string Name { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using ServiceStack.Redis;
namespace Datamodel
{
public class Repository
{
private static readonly PooledRedisClientManager m = new PooledRedisClientManager();
readonly static IDictionary<Type, List<object>> _cache = new ConcurrentDictionary<Type, List<object>>();
/// <summary>
/// Load {T} into object cache from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
public static void LoadIntoCache<T>() where T : class
{
_cache[typeof(T)] = RedisGetAll<T>().Cast<object>().ToList();
}
/// <summary>
/// Add single {T} into cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Create<T>(T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
list = new List<object>();
}
list.Add(entity);
_cache[typeof(T)] = list;
RedisStore<T>(entity);
}
}
/// <summary>
/// Find First {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindFirstBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).FirstOrDefault();
}
return null;
}
}
/// <summary>
/// Find Single {T} in object cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static T FindSingleBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).SingleOrDefault();
}
return null;
}
}
/// <summary>
/// Tries to update or Add entity to object cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq expression</param>
/// <param name="entity">entity</param>
public static bool AddOrUpdate<T>(Func<T, bool> predicate, T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
// Find Type cache.
List<object> list;
if (!_cache.TryGetValue(typeof(T), out list))
{
// Incase this tpye was not pre-loaded into cache we will cache new entities from here on out.
list = new List<object>();
}
// Look for old entity.
var e = list.Cast<T>().Where(predicate).FirstOrDefault();
// If no old record exists no problem we treat this as if its a new record.
if (e != null)
{
// Old record found removing it.
list.Remove(e);
}
// Regardless if object existed or not we add it to our Cache / Data Store.
list.Add(entity);
_cache[typeof(T)] = list;
}
// Redis does not care if record is new or old as it will Add or Update regardless.
RedisStore<T>(entity);
return true;
}
/// <summary>
/// Delete single {T} from cache and Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="entity">class object</param>
public static void Remove<T>(T entity) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
list.Remove(entity);
_cache[typeof(T)] = list;
RedisDelete<T>(entity);
}
}
}
/// <summary>
/// Find List<T>(predicate) in cache.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <param name="predicate">linq statement</param>
/// <returns></returns>
public static List<T> FindBy<T>(Func<T, bool> predicate) where T : class
{
// Lets prevent race conditions, locking down cache.
lock (_cache[typeof(T)])
{
List<object> list;
if (_cache.TryGetValue(typeof(T), out list))
{
return list.Cast<T>().Where(predicate).ToList();
}
return new List<T>();
}
}
/// <summary>
/// Get Next Sequence for the gien {T} Entity from Data Store.
/// </summary>
/// <typeparam name="T">class</typeparam>
/// <returns>long</returns>
public static long Next<T>() where T : class
{
return RedisNext<T>();
}
#region Redis Commands
//
// Following methods are ment as static private methods.
//
private static List<T> All<T>() where T : class
{
return RedisGetAll<T>().ToList();
}
private static long RedisNext<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetNextSequence();
}
private static void RedisDelete<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.As<T>().Delete(entity);
}
private static T RedisFind<T>(long id) where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetById(id);
}
private static IList<T> RedisGetAll<T>() where T : class
{
using (var ctx = m.GetClient())
return ctx.As<T>().GetAll();
}
private static void RedisStore<T>(T entity) where T : class
{
using (var ctx = m.GetClient())
ctx.Store<T>(entity);
}
#endregion
}
}
Hi I have written a Cached-Object store with a Redis Client for persistent storage, the. The application that is going to use this is a heavy read application with the occasional write,. I assume that entire model will contain somewhere around 500k - 1m entities, the. The tests I have done so far with a far more complicated model than I include as example shows that Entity Framework does not come close performance wise. Now that said I am curious if I have made any fatal mistakes in my Repository code.
Hi I have written a Cached-Object store with a Redis Client for persistent storage, the application that is going to use this is a heavy read application with the occasional write, I assume that entire model will contain somewhere around 500k - 1m entities, the tests I have done so far with a far more complicated model than I include as example shows that Entity Framework does not come close performance wise. Now that said I am curious if I have made any fatal mistakes in my Repository code.
I have written a Cached-Object store with a Redis Client for persistent storage. The application that is going to use this is a heavy read application with the occasional write. I assume that entire model will contain somewhere around 500k - 1m entities. The tests I have done so far with a far more complicated model than I include as example shows that Entity Framework does not come close performance wise. Now that said I am curious if I have made any fatal mistakes in my Repository code.