自己实现的一个缓存数据库(搞着玩) .net Core/6/8/9

自己实现的一个缓存数据库(搞着玩)

想法来源

做过一个小型项目,客户要求易移植,不能使用收费的数据库,最好是一个包搞定,尝试过用sqlite,在部分linux上可能需要自己安装环境,比较麻烦

mysql也需要安装,客户技术实力比较弱,不安装多的依赖,一键运行最好

特点说明

支持多线程
支持多表
适合小型项目,不用安装配置其它数据库,可以做到只有一个包,一键启动
如果将主键id调整为手动指定的字符串,可以作为系统的配置库来使用,数据都在内存里面,读取速度快
由于是数据是全量进行持久化保存,所以不支持太大的数据量

上代码

主体

csharp 复制代码
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);
            }
        }
    }
}

基类

csharp 复制代码
    public class CacheDBEntityBase
    {
        /// <summary>
        /// 主键
        /// </summary>
        public long Id { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreatedTime { get; set; }

        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime? UpdateTime { get; set; }
    }

测试类

csharp 复制代码
    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
上面代码中没有这些内容的实现,请自行实现替代

相关推荐
somethingGoWay10 小时前
wpf .netcore 导出docx文件
wpf·.netcore
somethingGoWay12 小时前
wpf .netcore 导出pdf文件
pdf·wpf·.netcore
切糕师学AI1 天前
如何建立针对 .NET Core web 程序的线程池的长期监控
java·前端·.netcore
csdn_aspnet2 天前
使用 MongoDB.Driver 在 C# .NETCore 中实现 Mongo DB 过滤器
mongodb·c#·.netcore
tiancao2222 天前
安装3DS MAX 2026后,无法运行,提示缺少.net core的解决方案
.net·.netcore·3dsmax
csdn_aspnet2 天前
使用 C# .NETCore 实现MongoDB
mongodb·c#·.netcore
MoFe16 天前
【.net core】【NPOI】读取表格信息(处理合并行表格数据)
.netcore
csdn_aspnet6 天前
在 .NET Core 中实现基于策略和基于角色的授权
.netcore·role·policy
The Sheep 20236 天前
.NetCore MVC
mvc·.netcore
一包烟电脑面前做一天6 天前
.NetCore下Ocelot + Nacos 实现负载均衡
nacos·负载均衡·.netcore·ocelot·ocelot集成nacos