Bonjour, je vous propose une implémentation d'architecture hybride sql/nosql utilisant l'ORM ServiceStack sur mon émulateur Dofus 2. Cette implémentation est mon adaptation de celle de Dr.Brook, le mérite lui revient donc n_n
Cette implémentation permet de répliquer des données d'une base de donnée persistante vers un "cache", le but étant de faire le traitement de ces données depuis ce "cache" qui lui se trouve en mémoire et non pas sur un serveur SQL distant (ou local).
L'intérêt d'une telle implémentation est de minimiser les interactions avec la base de donnée persistante. En effet, lorsque nous avons beaucoup de traitement à effectuer sur un même objet (un Character par exemple, lors d'une session de jeu, les données s'actualisent en permanence durant toute la session) cela peut vite devenir gourmand en ressource, il est donc intéressant d'utiliser un cache pour ces traitements. (ce rôle étant assuré par redis).
Une fois la session terminé, le model est répliqué en base de donnée, et la mémoire est libérée grâce à la méthode Swap().
Voici ma solution :
using ServiceStack.OrmLite;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Reflection;
using System.Data;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.IO;
using static System.Console;
public class DatabaseFactory : IDisposable
{
public OrmLiteConnectionFactory _dbConnectionFactory;
public RedisManagerPool _redisManagerPool;
public IDbConnection _connection;
public IRedisClient _redis;
public DatabaseFactory()
{ }
public DatabaseFactory(OrmLiteConnectionFactory factory, RedisManagerPool pool)
{
_dbConnectionFactory = factory;
_redisManagerPool = pool;
}
public void Init()
{
_connection = _dbConnectionFactory.Open();
_redis = _redisManagerPool.GetClient();
}
}
public T GetModelFromDb<T>(Expression<Func<T, bool>> predicate)
{
// ServiceStack return null automatically if model not found
return _connection.Single<T>(predicate);
}
public List<T> GetModelListFromDb<T>(Expression<Func<T, bool>> predicate)
{
return _connection.Select<T>(predicate);
}
public bool Exist<T>(Expression<Func<T, bool>> predicate)
{
if (_connection.Single<T>(predicate) != null)
return true;
else
return false;
}
public async Task Insert<T>(T model)
{
await _connection.InsertAsync<T>(model);
}
public async Task Update<T>(T model)
{
await _connection.UpdateAsync<T>(model);
}
public async Task Save<T>(T model)
{
await _connection.SaveAsync<T>(model);
}
public async Task ExecuteQuery(string s)
{
await _connection.ExecuteSqlAsync(s);
}
public void Dispose()
{
_connection.Close();
}
}
public class RedisManager<T>
where T : new()
{
public T Model { get; private set; }
private IRedisTypedClient<T> _redis;
private bool isRaw;
private RedisManager()
{
}
public static RedisManager<T> StoreModel(IRedisClient redis, T model)
{
// Get direct from model
var fact = new RedisManager<T>();
fact._redis = redis.As<T>();
fact.Model = model;
fact.isRaw = true;
fact._redis.Store(model);
return fact;
}
public T Save()
{
// Delete old and create new
_redis.Delete(Model);
_redis.Store(Model);
return Model;
}
public void Swap(DatabaseFactory _db)
{
if (isRaw)
_db.Insert<T>(Model);
else
_db.Update<T>(Model);
_redis.Delete(Model);
}
}
Si vous avez des questions n'hésitez pas !