简单的xml数据库设计
我的需求
有时候系统需要存储一些简单的关系型属性,不考虑并发,不考虑性能(一次操作在几ms),数据库没有其他依赖引用,拿过来就可以用
为什么选xml作为数据库?
- 可读性好
- 实体的对应关系不严格 ,
二进制序列化实体改动后不能读取以前序列化的数据,而且实体上面需要贴可序列化标签
数据库功能
- 无侵入存储实体,可存储poco对象,不需要在实体上面贴标签或继承什么
- 单例操作内存数据,只有初始化或者写入的时候才会读写文件,其他时候操作内存中的数据
使用指南
* 定义实体(public)
public class Friend{}
* 定义实体操作类,继承XmlDb<T>
public class FriendDbSet : XmlDb<Friend>
{
static FriendDbSet _instance = new FriendDbSet();
public static FriendDbSet GetInstance()
{
return _instance;
}
}
* 操作实体
Friend friend = new Friend() { Id = "1", name = "何仙姑" };
Friend friend2 = new Friend() { Id = "1", name = "何仙姑2" };
//添加
FriendDbSet.GetInstance().Add(friend2);
//删除
FriendDbSet.GetInstance().Remove(r => r.Id == "1");
//修改
friend.name = "何惠惠";
FriendDbSet.GetInstance().UpdateByIdOrKey(friend);
//查询
var result = FriendDbSet.GetInstance().ToList().Where(r => r.name.StartsWith("何"));
>也可以不定义实体操作类直接进行如下操作
>XmlDb<Friend>.GetInstance().Add(u);//增加
>XmlDb<Friend>.GetInstance().Remove(r=>r.Age>1000);//根据条件删除
>XmlDb<Friend>.GetInstance().Remove("key");//根据key或id删除
>XmlDb<Friend>.GetInstance().UpdateByIdOrKey(new User() { });//修改
>XmlDb<Friend>.GetInstance().ToList();//查询全部
>XmlDb<Friend>.GetInstance().Find("key");//查询单个
代码(使用单例模式,模版方法模式)
public class XmlDb where T : new()
{
private static XmlDb instance = new XmlDb();
public static XmlDb<T> GetInstance()
{
return instance;
}
private List<T> entityList = new List<T>();
public XmlDb()
{
this.SetDbFile();
this.ReadDb();
}
private string dbFile;
private string Dbfile
{
get { return dbFile; }
set
{
if (!string.IsNullOrEmpty(value) && !value.Equals(dbFile))
{
this.entityList.Clear();
}
dbFile = value;
this.ReadDb();
}
}
protected virtual void ReadDb()
{
if (File.Exists(this.Dbfile))
{
XmlSerializer ks = new XmlSerializer(typeof(List<T>));
Stream reader = new FileStream(this.Dbfile, FileMode.Open, FileAccess.ReadWrite);
this.entityList = ks.Deserialize(reader) as List<T>;
reader.Close();
}
else
{
this.entityList = new List<T>();
}
}
protected virtual void SetDbFile()
{
string folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "storage", "litedb");
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
Type type = typeof(T);
if (string.IsNullOrEmpty(this.Dbfile))
{
//获取全名称签名,防止类名重复
string md5Sign = BitConverter.ToString(MD5.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(type.FullName))).Replace("-", "");
this.Dbfile = Path.Combine(folder, type.Name + "_" + md5Sign + ".xml");
}
}
protected virtual void WriteDb()
{
//异常处理
string tempFileName = this.dbFile.Replace(".xml", "_Temp.xml");
try
{
XmlSerializer ks = new XmlSerializer(typeof(List<T>));
FileInfo fi = new FileInfo(this.Dbfile);
var dir = fi.Directory;
if (!dir.Exists)
{
dir.Create();
}
//缓存数据防止读写失败
if (fi.Exists)
{
fi.CopyTo(tempFileName, true);
}
Stream writer = new FileStream(this.Dbfile, FileMode.Create, FileAccess.ReadWrite);
ks.Serialize(writer, this.entityList);
writer.Close();
//删除缓存数据
if (File.Exists(tempFileName))
{
File.Delete(tempFileName);
}
UpdateSchema();
}
catch (Exception ex)
{
//恢复数据
throw ex;
}
}
/// <summary>
/// 更新数据的元数据信息
/// </summary>
private void UpdateSchema()
{
string root = Path.GetDirectoryName(this.Dbfile);
var files = Directory.GetFiles(root, "*.xml").Where(r => !r.EndsWith("schema.xml")).Select(r => Path.GetFileName(r));
//构建xml并存储
string schemaFile = Path.Combine(root, "schema.xml");
XDocument xdoc = new XDocument();
XElement xmlroot = new XElement("root");
xdoc.Add(xmlroot);
foreach (var item in files)
{
xdoc.Root.Add(new XElement("fileName", item));
}
xdoc.Save(schemaFile);
}
/// <summary>
/// 根据主键或Id获取实体对象
/// </summary>
/// <param name="KeyOrId"></param>
/// <returns></returns>
public T Find(string KeyOrId)
{
Type t = typeof(T);
foreach (var inst in this.entityList)
{
foreach (PropertyInfo pro in t.GetProperties())
{
var keyattr = pro.GetCustomAttribute(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false);
if (keyattr != null || pro.Name.ToLower() == "id")
{
if (pro.GetValue(inst, null)?.ToString() == KeyOrId)
{
return inst;
}
}
}
}
return default(T);
}
public void Add(T entity)
{
this.entityList.Add(entity);
this.WriteDb();
}
public void AddRange(List<T> list)
{
this.entityList.AddRange(list);
this.WriteDb();
}
public List<T> ToList()
{
this.ReadDb();
return entityList;
}
/// <summary>
/// 根据条件移除元素
/// </summary>
/// <param name="filters"></param>
public void Remove(Predicate<T> filters)
{
this.entityList.RemoveAll(filters);
this.WriteDb();
}
/// <summary>
/// 根据key或id移除元素
/// </summary>
/// <param name="filters"></param>
public void Remove(string KeyOrId)
{
Type t = typeof(T);
T entity = default(T);
foreach (var inst in this.entityList)
{
foreach (PropertyInfo pro in t.GetProperties())
{
var keyattr = pro.GetCustomAttribute(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false);
if (keyattr != null || pro.Name.ToLower() == "id")
{
if (pro.GetValue(inst, null)?.ToString() == KeyOrId)
{
entity = inst;
goto FinishLoop;
}
}
}
}
FinishLoop:
entityList.Remove(entity);
this.WriteDb();
}
public void UpdateByIdOrKey(T entity)
{
Type t = typeof(T);
string id = string.Empty;
foreach (PropertyInfo pro in t.GetProperties())
{
var keyattr = pro.GetCustomAttribute(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false);
if (keyattr != null || pro.Name.ToLower() == "id")
{
id = pro.GetValue(entity, null)?.ToString();
break;
}
}
this.Remove(id);
this.Add(entity);
}
/// <summary>
/// 清空列表
/// </summary>
/// <param name="filters"></param>
public void Clear()
{
entityList.Clear();
this.WriteDb();
}
}
简单的xml数据库设计的更多相关文章
- NetCore微服务简单流程审批数据库设计及后台服务开发
1.数据库设计 -- ---------------------------- -- Table structure for TBase_Flow -- ----------------------- ...
- day39 python 学习 数据库学习 五个约束,数据库设计(一对一,一对多等等)
删除重复数据: 注意数据库不能又查又删 *******#删除作者为重复数据并保留ID最大的是数据 delete from ren where author in (select * from(sel ...
- MySQL 约束和数据库设计
1.MySQL 约束: 1.约束的概念: 约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性.唯一性. MySQL中,常用的几种约束: 约束类型: 非空 主键 唯一 外键 默认值 ...
- 基于XML数据库的学生信息管理系统的设计与实现
本项目是在学习之余写的,主要用来练习MVC+DAO的分层设计思想,项目基于一个简单的XML学生数据库,使用XML作为数据库的原因是其十分的小巧与方便,使用dom4j即可进行方便的解析.因为这段时间课程 ...
- 数据库设计 Step by Step (1)——扬帆启航
引言:一直在从事数据库开发和设计工作,也看了一些书籍,算是略有心得.很久之前就想针 对关系数据库设计进行整理.总结,但因为种种原因迟迟没有动手,主要还是惰性使然.今天也算是痛下决心开始这项卓绝又令我兴 ...
- mysql 数据库设计(转)
本规范适用于mysql 5.1或以上版本使用 数据库范式 第一范式(1NF)确保每列保持原子性 第一范式(1NF):数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项. ...
- 转载unity编辑器xml数据库插件
unity编辑器xml数据库插件 注:9月9日更新,其中MyXML.cs中有一句代码写错,查找功能失误,文中已经修改! 注:9月1日更新说明:xml存储结构,因为在用xml之前不知道正规的xml数据结 ...
- 数据库设计中的Soft Delete模式
最近几天有点忙,所以我们今天来一篇短的,简单地介绍一下数据库设计中的一种模式——Soft Delete. 可以说,该模式毁誉参半,甚至有非常多的人认为该模式是一个Anti-Pattern.因此在本篇文 ...
- 使用django开发博客过程记录1——数据库设计
1.数据库设计 2.插入测试数据 3.配置相关问题 1.数据库设计 数据库有简单的三张表:Article.Category.Tag以下是代码 # -*- coding:utf-8 -*- from _ ...
随机推荐
- JZOJ2020年8月7日提高组反思
JZOJ2020年8月7日提高组反思 T1 暴力枚举 枚举起点和\(p\) 然后就 过了?! 根据本人不严谨的推算 时间复杂度\(O(\dfrac{n^7}{4})\) 数据太水就过去了QAQ T2 ...
- Markdown实用教程
Markdown 是用来编写结构化文档的一种纯文本格式,它使我们在双手不离开键盘的情况下,可以对文本进行一定程度的格式排版.markdown语法是通用的,很多写作平台都是支持markdown的,比如简 ...
- 第15.4节 PyCharm程序代码检测功能介绍
老猿使用PyCharm有将近一个月了,发现PyCharm并不能很好的完成语法检查,有时运行时突然终止,仔细核查却发现是基本的语法错误,不过有次无意中移动鼠标到代码最右边的边框时发现其实PyCharm有 ...
- SZhe_Scan碎遮:一款基于Flask框架的web漏洞扫描神器
SZhe_Scan碎遮:一款基于Flask框架的web漏洞扫描神器 天幕如遮,唯我一刀可碎千里华盖,纵横四海而无阻,是谓碎遮 --取自<有匪> 写在前面 这段时间很多时间都在忙着编写该项目 ...
- Scrum 冲刺 第五篇
Scrum 冲刺 第五篇 每日会议照片 昨天已完成工作 队员 昨日完成任务 黄梓浩 初步完成app项目架构搭建 黄清山 完成部分个人界面模块数据库的接口 邓富荣 完成后台首页模块数据库的接口 钟俊豪 ...
- 对网页接口的追踪探索(以b站通过bv号查询av号为例
对网页接口的追踪探索(以b站通过bv号查询av号为例 序言 本文只提供一种探索网页加载时后端访问接口情况的思路,所举例子没有太大实际用处. 一 自2020年3月23日起,AV号将全面升级到BV号.但是 ...
- 将一个数组转化为需要的格式,来自react官网的商品列表示例
//原来的格式 const PRODUCTS = [ { category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Foot ...
- VMware虚拟机下Centos8 设置静态IP地址
缘起 我们在平时学习Redis.Nginx等分布式微服务的组件的时候,无法避免的需要用到Linux操作系统,而Linux操作系统的主机来源差不多就三种情况: 真实物理机 阿里云等云服务器 利用虚拟机 ...
- kafka-java消费者与生产者代码示例
引入依赖 <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.11 ...
- 戴尔iDRAC+Ubuntu 18.04系统安装
Ubuntu镜像下载链接:http://mirrors.aliyun.com/ubuntu-releases/18.04/ 1.登录戴尔管理口 2.点击虚拟控制台 3.选择镜像 4.挂载镜像 5.选择 ...