当前位置: 首页 > article >正文

自己实现的一个缓存数据库(搞着玩) .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
上面代码中没有这些内容的实现,请自行实现替代


http://www.kler.cn/a/533801.html

相关文章:

  • CTP查询资金费率和手续费没响应
  • C/C++编译器
  • 离散时间傅里叶变换(DTFT)公式详解:周期性与连续性剖析
  • 014-STM32单片机实现矩阵薄膜键盘设计
  • Linux第105步_基于SiI9022A芯片的RGB转HDMI实验
  • [mmdetection]fast-rcnn模型训练自己的数据集的详细教程
  • 【C语言高级特性】位操作(二):应用场景
  • python开发:爬虫示例——GET和POST请求处理
  • vue2-给data动态添加属性
  • WPS中解除工作表密码保护(忘记密码)
  • 手写MVVM框架-实现v-model(单向绑定)
  • rabbitMQ数据隔离
  • 1 HBase 基础
  • PHP 中 `foreach` 循环结合引用使用时可能出现的问题
  • 【C++】STL——vector的使用
  • 【自然语言处理(NLP)】生成词向量:ELMo(Embedded from Language Models)原理及应用
  • 硬件电路基础
  • 每日Attention学习20——Group Shuffle Attention
  • DeepSeek-V3 大模型哪些地方超越了其他主流大模型
  • 中国通信企业协会 通信网络安全服务能力评定 风险评估二级要求准则
  • 保姆级教程Docker部署Zookeeper官方镜像
  • FPGA学习篇——Verilog学习1
  • Shell条件变量替换
  • PySpark学习笔记5-SparkSQL
  • 在游戏本(6G显存)上本地部署Deepseek,运行一个14B大语言模型,并使用API访问
  • 记录debian12运行时出现卡死的问题