简单的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 _ ...
随机推荐
- chrome浏览器查看当前页面cookie
方法一:点进去设置--高级--网站设置--权限cookie--查找所有cookie和网站数据,就可以看到所有的cookie信息了,举例: 方法二:键盘F12,找到network--点击Doc(如果没有 ...
- SQL优化之SQL 进阶技巧(下)
上文( SQL优化之SQL 进阶技巧(上) )我们简述了 SQL 的一些进阶技巧,一些朋友觉得不过瘾,我们继续来下篇,再送你 10 个技巧 一. 使用延迟查询优化 limit [offset], [r ...
- Cys_Control(四) MTabControl
一.查看TabControl原样式 <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name ...
- 利用Python特殊变量__dict__快速实现__repr__的一种方法
在<第8.15节 Python重写自定义类的__repr__方法>.<Python中repr(变量)和str(变量)的返回值有什么区别和联系>.<第8.13节 Pytho ...
- 虚拟IP原理及使用
一.前言 高可用性 HA(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性.HA 系统是目前企业防止核心 ...
- 第五篇 Scrum 冲刺博客
一.站立式会议 1. 会议照片 2. 工作汇报 团队成员名称 昨日(26日)完成的工作 今天(27日)计划完成的工作 工作中遇到的困难 陈锐基 - 完成发布页面的布局- 完成发布动态的功能 - 优化当 ...
- Scrum冲刺_Day03
一.团队展示: 1.项目:light_note备忘录 2.队名:删库跑路队 3.团队成员 队员(不分先后) 项目角色 黄敦鸿 后端工程师.测试 黄华 后端工程师.测试 黄骏鹏 后端工程师.测试 黄源钦 ...
- Devpress (DxReport)使用ReportDesigner (一) 基本功能
1. Devpress (DxReport)编辑 (1) 新建一个XtraReport. (2) 在报告上点右键添加元素: 元素说明: (1) 其中有报告头,报告尾,页头,页尾,组头,组尾,详细. ...
- 状压DP复习笔记
前言 复习笔记第4篇.CSP RP++. 引用部分为总结性内容. 0--P1433 吃奶酪 题目链接 luogu 题意 房间里放着 \(n\) 块奶酪,要把它们都吃掉,问至少要跑多少距离?一开始在 \ ...
- MVC部署出现403.14问题记录
1.问题截图 2.解决办法有几种 1)在system.webServer下增加,这种是不推荐的. <modules runAllManagedModulesForAllRequests=&quo ...