简单的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 _ ...
随机推荐
- Django 多对多表的三种创建方式
第一种: class Book(models.Model): name = models.CharField(max_length=32) # 第一种自动创建 authors = models.Man ...
- C++编程指南续
三. 命名规则 比较著名的命名规则当推Microsoft公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入前缀以增进人们对程序的理解".例如所有的 ...
- 老猿学5G:多量纲计费与QoS的QCI、5QI、ARP、GBR和MBR
☞ ░ 前往老猿Python博文目录 ░ 一.多量纲计费 多量纲计费是与传统的计费模式相区别的一种计费模式,传统的计费基本上都是通过使用量.使用时长或包固定时长等方式计费,而多量纲计费是指在考虑以上方 ...
- 第12.4节 Python伪随机数数生成器random模块导览
random模块实现了各种分布的伪随机数生成器,常用功能包括: random.seed(a=None, version=2):初始化随机数生成器,如果 a 被省略或为 None ,则使用当前系统时间. ...
- PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的ButtonRole详解
一.引言 在Designer中创建的QDialogButtonBox对应的Button,都有指定的ButtonRole,而我们创建自定义的Button加入到QDialogButtonBox中去时,也需 ...
- 《Machine Learning in Action》—— Taoye给你讲讲Logistic回归是咋回事
在手撕机器学习系列文章的上一篇,我们详细讲解了线性回归的问题,并且最后通过梯度下降算法拟合了一条直线,从而使得这条直线尽可能的切合数据样本集,已到达模型损失值最小的目的. 在本篇文章中,我们主要是手撕 ...
- 性能测试学习之路 (二)jmeter详解(jmeter执行顺序 && 作用域 && 断言 && 事务 &&集合点 )
1 Jmeter 工作区介绍 jmeter工作区分为3个部分:目录树.测试计划编辑区域.菜单栏. 2 Jmeter 执行顺序规则 Jmeter执行顺序规则如下: 配置元件 前置处理器 定时器 采样器s ...
- Nday漏洞组合拳修改全校师生密码
很久以前写的文章了,发一下:) 本文是我真实的挖洞经历.撰写本文时相关学校已修复漏洞,相关漏洞也提交给了教育漏洞平台.纯粹是挖洞经验的总结和技术分享,由于敏感信息比较多,所以文章里面很多图片已经面目全 ...
- flask中的重定向,渲染,反转视图函数
在学习flask中,重定向,渲染,反转老是不怎么明白,今天明白了其中的点了,来给大家分享下 rend_templete()这个函数就是一个渲染的作用,渲染html的东西. url_for是反转视图函数 ...
- apache、nginx、Tomcat、IIS引擎解析漏洞
引擎解析漏洞 常见的web容器有IIS.Apache.Nginx.Tomcat等,以下是详细讲解 IIS IIS简介 是 ...