自己实现的一个缓存数据库(搞着玩) .net Core/6/8/9
自己实现的一个缓存数据库(搞着玩)
- 想法来源
- 特点说明
- 上代码
- 主体
- 基类
- 测试类
- `注`
想法来源
做过一个小型项目,客户要求易移植,不能使用收费的数据库,最好是一个包搞定,尝试过用sqlite,在部分linux上可能需要自己安装环境,比较麻烦
mysql也需要安装,客户技术实力比较弱,不安装多的依赖,一键运行最好
特点说明
支持多线程
支持多表
适合小型项目,不用安装配置其它数据库,可以做到只有一个包,一键启动
如果将主键id调整为手动指定的字符串,可以作为系统的配置库来使用,数据都在内存里面,读取速度快
由于是数据是全量进行持久化保存,所以不支持太大的数据量
上代码
主体
namespace Memory.Db
{
/// <summary>
/// 内存数据库
/// 支持多线程
/// 支持多表
/// 不支持大量数据
/// 建议每个表数据量不要超过1w,或者数据文件大小保持在5M以内
/// 数据都在内存里面,所以读取速度会相当快
/// 适合项目
/// 1.小型项目
/// 2.数据量小 不想使用数据库,安装配置麻烦
/// </summary>
public class CacheDB:ISingleton
{
/// <summary>
/// 雪花id类
/// </summary>
readonly SnowflakeId _sid;
public CacheDB(SnowflakeId sid)
{
_sid = sid;
}
//数据库
private static ConcurrentDictionary<string, ConcurrentDictionary<long, dynamic>> _db = new();
//数据存放路径
private string _fielpath = "wwwroot/cachedb/";
//锁对象
private object lockobj = new object();
/// <summary>
/// 新增或修改
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public T AddOrUpdate<T>(T item) where T : CacheDBEntityBase, new()
{
//取得表
var table = GetTable<T>();
//判断是否新增
if (item.Id == 0)
{
//新增
item.Id = _sid.GenerateId();
item.CreatedTime = DateTime.Now;
}
else
{
//修改
if (!table.ContainsKey(item.Id)) throw new Exception("数据不存在");
var old = table[item.Id];
item.CreatedTime = old.CreatedTime;//将原来的创建时间值取过来,防止被空值覆盖
item.UpdateTime = DateTime.Now;
}
///新增或修改
table.AddOrUpdate(item.Id, item, (a, b) => item);
//保存快照
SaveToFile<T>();
return item;
}
/// <summary>
/// 删除
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item"></param>
/// <exception cref="Exception"></exception>
public void Delete<T>(T item) where T : CacheDBEntityBase, new()
{
//取得表
var table = GetTable<T>();
//按id删除
if (item.Id == 0) throw new Exception("未提供Id");
if (table.ContainsKey(item.Id))
{
table.Remove(item.Id, out _);
//保存快照
SaveToFile<T>();
}
}
/// <summary>
/// 返回列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public List<T> GetList<T>() where T : CacheDBEntityBase, new()
{
var table = GetTable<T>();
//这里先序列化成json,再序列化为指定类型,不然会出现值为空的情况
var json = table.ToJson();
var data = json.ToEntity<Dictionary<long, T>>();
return data.Select(x => x.Value).ToList();
}
/// <summary>
/// 按id查询单条
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <returns></returns>
public T Find<T>(long id) where T : CacheDBEntityBase, new()
{
var table = GetTable<T>();
var mod= table[id] as T;
return mod;
}
/// <summary>
/// 取得表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public ConcurrentDictionary<long, dynamic> GetTable<T>() where T: CacheDBEntityBase,new()
{
//获取表名
var _table = typeof(T).Name;
ConcurrentDictionary<long, dynamic> data;
//判断表是否已经存在于缓存
if (!_db.ContainsKey(_table))
{
//保存路径
var _path = $"{_fielpath}{_table}.json";
if (File.Exists(_path))
{
//如果文件存在,从文件读取数据到缓存
var json = File.ReadAllText(_path);
_db[_table] = json.ToEntity<ConcurrentDictionary<long, dynamic>>();
}
else
{
//如果文件不存在,创建新的表
_db[_table] = new ConcurrentDictionary<long, dynamic>();
}
}
data = _db[_table];
//返回表
return data;
}
/// <summary>
/// 快照
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private async Task SaveToFile<T>()
{
lock (lockobj)
{
var _table = typeof(T).Name;
var json = _db[_table].ToJson();
var _path = $"{_fielpath}{_table}.json";
Directory.CreateDirectory(_fielpath);
File.WriteAllText(_path, json);
}
}
}
}
基类
public class CacheDBEntityBase
{
/// <summary>
/// 主键
/// </summary>
public long Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedTime { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime? UpdateTime { get; set; }
}
测试类
public class aa: CacheDBEntityBase
{
public string name { get; set; }
public string name2 { get; set; }
public string name3 { get; set; }
public string name4 { get; set; }
public string name5{ get; set; }
}
public class bb : CacheDBEntityBase
{
public string name { get; set; }
}
注
上面代码中的部分内容说明
ToJson
方法将实体转为json字符串
ToEntity
方法将json字符串转为指定的类型
SnowflakeId
雪花id类 用来生成id
上面代码中没有这些内容的实现,请自行实现替代