gpt4 book ai didi

c# - 缓存数据库查询的最佳方法是什么

转载 作者:太空宇宙 更新时间:2023-11-03 13:39:52 24 4
gpt4 key购买 nike

我正在编写一个管理智能应用程序,它需要大量复杂的数据库查询,其中一些查询非常昂贵。为了提高性能,我大量使用 Memcached 在内存中存储尽可能多的数据。

这导致我的代码中出现大量重复,我很想摆脱这些重复并构建一个更干净的数据访问解决方案。我的很多数据访问函数最终看起来像这样..

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;
}

我只是不太确定标准方法是什么,它是否涉及使用自定义属性类或类似的东西?

最佳答案

这是一个横切关注点。 Decorator 模式可能适用于此。我可能对这种模式没有经验,但我会试一试

// 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; });
}
}

请注意:

  • 我没有测试过这段代码,不知道它是否功能齐全。我只是描述插图
  • 是的,通过为 Find 重载 ICacheableRepository 有代码味道,但是我无法使用 Expression 作为 Key 字典

优点:

  • 此 CachedRepositoryDe​​corator 可用于任何通用存储库(可重用)
  • 选择过程中没有缓存逻辑,强调SRP

缺点:

  • 没有 ORM 很难实现,也许你需要通过反射进行一些调整以使其在没有 ORM 的情况下工作
  • 一开始很难理解
  • 没有 DI 容器很难连线

归功于此article :)

关于c# - 缓存数据库查询的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17484794/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com