简单的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 _ ...
随机推荐
- SkyWalking —— 分布式应用监控与链路追踪
SkyWalking 是一个应用性能监控系统,特别为微服务.云原生和基于容器(Docker, Kubernetes, Mesos)体系结构而设计.除了应用指标监控以外,它还能对分布式调用链路进行追踪. ...
- 深圳-2020-java面试题分享
记录一下最近面试接触的面试题. 深圳掌众传媒: union 和union all区别 union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: union All:对两个结果集进行 ...
- 使用 Jasypt 加密 Spring Boot 配置文件
一.添加依赖包 <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId> ...
- vm虚拟机安装centos7。克隆镜像以及快照
为了方便下次安装配置,保存一篇安装centos的文章 https://blog.csdn.net/wsq119/article/details/80635558 步骤非常详细,一看就会. 这一篇是关于 ...
- python3 通过 pybind11 使用Eigen加速代码
python是很容易上手的编程语言,但是有些时候使用python编写的程序并不能保证其运行速度(例如:while 和 for),这个时候我们就需要借助c++等为我们的代码提速.下面是我使用pybind ...
- 第二十七章、containers容器类部件QTabWidget选项窗部件详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析
一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...
- 本地web项目部署到服务器里连接不上数据库的解决办法
今天突然想到把自己之前的项目挂到服务器上,但是用到了数据库,于是给服务器装上了MySQL,想着能赶紧把项目挂上去看看效果,然后并不是一帆风顺,在奋斗了四小时后终于解决了问题的所在. (1)首先我找到了 ...
- kaggle——Bag of Words Meets Bags of Popcorn(IMDB电影评论情感分类实践)
kaggle链接:https://www.kaggle.com/c/word2vec-nlp-tutorial/overview 简介:给出 50,000 IMDB movie reviews,进行0 ...
- window下kettle安装
参考这篇文章 http://note.youdao.com/noteshare?id=a8c536ba952a48d60d7ea8f2cc61a94b