首先祝大家新年快乐.身体健康,平安就是福气.

对于一般的个人迷你项目,数据量不大的时候,完全没有必要使用数据库,管理数据使用XML就可以了.

自己尝试写了一个XML数据库,插入1w条小记录,大概3M大小,然后将一半数据进行更新,大约耗时3秒钟.

XML数据库其实就是一个内存数据库,数据都在内存里面,速度不慢.

然后由于是XML序列化的,其实ORM也不需要了.每个数据库文件保存一种格式的数据.

废话不说,上代码

先是数据模型:

/*
* Created by SharpDevelop.
* User: scs
* Date: 2014/12/30
* Time: 14:07
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using DevKit.Common;
namespace DevKit.HtmlUtility
{
/// <summary>
/// Description of Class1.
/// </summary>
[Serializable]
public class CodeSnap
{
/// <summary>
/// 标题
/// </summary>
public string Title = string.Empty;
/// <summary>
/// 描述
/// </summary>
public string Descrpition = string.Empty;
/// <summary>
/// 类别
/// </summary>
public string Catalog = string.Empty;
/// <summary>
/// Tag
/// </summary>
public string Tag = string.Empty;
/// <summary>
/// 代码
/// </summary>
public string Code = string.Empty;
/// <summary>
/// 检索
/// </summary>
/// <param name="strKeyword">检索关键字</param>
/// <returns></returns>
Boolean Search(string strKeyword)
{
return false;
} }
}

数据模型是领域的数据,但是删除标志,更新时间这些数据库使用的字段也是需要的.由于需要序列化,必须打上[Serializable]

    /// <summary>
/// 数据库记录
/// </summary>
[Serializable]
public class Model<T>
{
/// <summary>
/// 删除标志
/// </summary>
public Boolean IsDel;
/// <summary>
/// 统一编号
/// </summary>
public string DBId;
/// <summary>
/// 最后更新时间
/// </summary>
public DateTime LastUpdate;
/// <summary>
/// 数据
/// </summary>
public T DataRec;
}

最后是数据库引擎的代码,这里用到了深拷贝

    /// <summary>
/// 数据库引擎
/// </summary>
public class XmlDataBase<T>
{
/// <summary>
/// 数据库状态
/// </summary>
public string Status = "Close";
/// <summary>
/// 数据表
/// </summary>
List<Model<T>> list = new List<Model<T>>();
/// <summary>
/// 数据库文件
/// </summary>
string DBfilename = string.Empty;
/// <summary>
/// 数据库记录数[Without IsDel]
/// </summary>
/// <returns></returns>
public int getCount()
{
return list.Count(x => {
return !x.IsDel;
});
}
/// <summary>
/// 数据库记录数[With IsDel]
/// </summary>
/// <returns></returns>
public int getCountWithDel()
{
return list.Count;
}
/// <summary>
/// 新建并且打开数据库
/// </summary>
/// <param name="xmlfilename"></param>
public XmlDataBase(string xmlfilename)
{
DBfilename = xmlfilename;
if (System.IO.File.Exists(xmlfilename)) {
list = Utility.LoadObjFromXml<List<Model<T>>>(DBfilename);
}
}
/// <summary>
/// 压缩数据库
/// </summary>
public void Compress()
{
var Compresslist = new List<Model<T>>();
Func<Model<T>,Boolean> inner = (x) => {
return (!x.IsDel);
};
Compresslist = list.FindAll(new Predicate<Model<T>>(inner));
list = Compresslist;
Commit();
}
/// <summary>
/// 添加
/// </summary>
/// <param name="rec"></param>
public void AppendRec(T rec)
{
var dbrec = new Model<T>();
dbrec.DBId = Guid.NewGuid().ToString();
dbrec.DataRec = Common.Utility.DeepCopy(rec);
dbrec.LastUpdate = DateTime.Now;
list.Add(dbrec);
}
/// <summary>
/// 删除
/// </summary>
/// <param name="rec"></param>
public void DelRec(Model<T> rec)
{
rec.IsDel = true;
UpdateDB(Utility.DeepCopy(rec));
}
/// <summary>
/// 更新
/// </summary>
/// <param name="rec"></param>
public void UpdataRec(Model<T> rec)
{
UpdateDB(Utility.DeepCopy(rec));
}
/// <summary>
/// 数据的修改
/// </summary>
/// <param name="rec">传递过来对象的深拷贝</param>
void UpdateDB(Model<T> rec)
{
for (int i = ; i < list.Count; i++) {
if (rec.DBId == list[i].DBId) {
rec.LastUpdate = DateTime.Now;
//不允许内部数据使用外部数据的指针引用
//这里使用深拷贝
list[i] = rec;
break;
}
}
}
/// <summary>
/// 提交更新
/// </summary>
public void Commit()
{
Utility.SaveObjAsXml(DBfilename, list);
}
/// <summary>
/// 检索
/// </summary>
/// <param name="SearchMethod"></param>
/// <returns>数据对象的深拷贝</returns>
public List<Model<T>> Search(Func<T,Boolean> SearchMethod)
{
Func<Model<T>,Boolean> inner = (x) => {
return (SearchMethod(x.DataRec) && !x.IsDel);
};
List<Model<T>> t = new List<Model<T>>();
foreach (Model<T> element in list.FindAll(new Predicate<Model<T>>(inner))) {
//这里也是将数据的副本给与外部
t.Add(Utility.DeepCopy(element));
}
return t;
}
}

数据库内部有一个列表,列表里面存放着数据记录,每个数据记录包括[业务数据]和[数据库信息]

数据的读取,给外部的是一个数据的深拷贝,这样的话,保证了外部对于数据的修改不会影响内部数据.

在传统的数据库中,一般都是通过TCP协议交换数据的,所以,数据其实也是一个深拷贝.

读取如此,保存数据也是将列表替换为一个外部对象的深拷贝.

每次保存数据的时候,其实是将所有的数据都写入数据XML文件中,当然,数据量少的前提下,这样做是可以的.

下面是一个使用的例子:数据库的New语句

            Common.XmlDataBase<CodeSnap> db= new Common.XmlDataBase<CodeSnap>(@"C:\中和软件\CodeSnap.xml");;
        void BtnAppendClick(object sender, EventArgs e)
{
Stopwatch x = new Stopwatch();
x.Start();
for (int i = ; i < ; i++) {
var r = new CodeSnap();
r.Title = "Title" + i.ToString();
r.Descrpition = "Descrpition";
r.Tag = "Tag";
r.Code = "Code";
db.AppendRec(r);
}
db.Commit();
var t = db.Search((m) => {
return true;
});
for (int i = ; i < t.Count; i++) {
if (i % == ) {
t[i].DataRec.Title = "New Title";
db.UpdataRec(t[i]);
}
}
db.Commit();
x.Stop();
MessageBox.Show(x.Elapsed.ToString());
}

这个只是一个XML数据的雏形,原代码基本上都在这里了.

可以改进的地方大概如下:NameSpace这些XML特有的属性的去除.

<ArrayOfModelOfCodeSnap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

现在Key是用GUID的,这个东西也蛮大的,如果不考虑压缩数据库的问题,可以使用数字连番.

(如果使用数字连番的话,由于压缩数据库会改变数据记录数,可能出现主健重复的问题)

其他压缩,例如时间,现在使用标准的DateTime.Now,所以时间也很冗长.以后可以将时间格式化后,保存为文字列.

    <IsDel>false</IsDel>
<DBId>ef65bff8-4951-464d-bd8f-432f1148b9f8</DBId>
<LastUpdate>2014-12-31T11:02:43.5750566+08:00</LastUpdate>

当然,XML也可以换成JSON的,这样的话,数据可以更小,但是JSON操作还不是NET内置的功能,所以暂时不使用.

里面用到的XML操作和深拷贝代码如下

        }
/// <summary>
/// 保存对象
/// </summary>
public static void SaveObjAsXml<T>(string filename, T Obj)
{
var xml = new XmlSerializer(typeof(T));
var writer = new StreamWriter(filename);
xml.Serialize(writer, Obj);
writer.Close();
}
/// <summary>
/// 读取对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filename"></param>
/// <returns></returns>
public static T LoadObjFromXml<T>(string filename)
{
var xml = new XmlSerializer(typeof(T));
var reader = new StreamReader(filename);
T obj = (T)xml.Deserialize(reader);
reader.Close();
return obj;
}
/// <summary>
/// 深拷贝
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static T DeepCopy<T>(T obj){
BinaryFormatter bFormatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
bFormatter.Serialize(stream, obj);
stream.Seek(, SeekOrigin.Begin);
return (T)bFormatter.Deserialize(stream);
}

提高生产性工具(四) - XML数据库的尝试的更多相关文章

  1. 提高生产性工具 - Model代码生成器(NET / JAVA) (一)

    原来在上一家公司,整整一年都在做工具,提高生产性,那个项目特别巨大,所以总共为老东家节约了500K左右的美金. (除了表扬之外,我个人什么好处都没有,领导们都升官发财了,郁闷) 到了新公司,也准备开发 ...

  2. XML数据库的尝试

    首先祝大家新年快乐.身体健康,平安就是福气. 对于一般的个人迷你项目,数据量不大的时候,完全没有必要使用数据库,管理数据使用XML就可以了. 自己尝试写了一个XML数据库,插入1w条小记录,大概3M大 ...

  3. 提高生产性工具(五) - 数据的过滤器和图形化(适用于 MVC5 + MongoDB)

    在下面流水账似的文章之前,先将一些感悟说一下. 1.如果一个系统对于某个功能在至少三个地方使用的话,必须将其抽象提炼出来,而且时间点最好是大规模测试之前. 2.提炼出来的功能,如果品质做得好,整个系统 ...

  4. 提高生产性工具 - Model代码生成器(二)

    首先,我想阐述一下我开发这个工具的一个观点. 如果大家做过对日软件的话,很多时候,日方是进行设计的,数据模型是什么样子的,各个字段的类型,需要做什么验证,验证规则,错误信息,都是日方制定的. 外包就是 ...

  5. [原创] debian 9.3 搭建Jira+Confluence+Bitbucket项目管理工具(四) -- 安装crowd 3.1.2

    [原创] debian 9.3 搭建Jira+Confluence+Bitbucket项目管理工具(四) -- 安装crowd 3.1.2 本来已经安装完毕, 并使用Jira集成的OAuth账户管理, ...

  6. Laravel教程 四:数据库和Eloquent

    Laravel教程 四:数据库和Eloquent 此文章为原创文章,未经同意,禁止转载. Eloquent Database 上一篇写了一些Laravel Blade的基本用法和给视图传递变量的几种方 ...

  7. (SQL SERVER) (ORACLE) (ACCESS)(POSTGRE SQL)四种数据库操作C#代码

    将对这四种数据库的操作封装到了2个类中可以拷贝过去直接使用. public sealed class OleDbClass { #region private utility methods & ...

  8. [原创] debian 9.3 搭建Jira+Confluence+Bitbucket项目管理工具(四) -- 安装bitbucket 5.7.0

    [原创] debian 9.3 搭建Jira+Confluence+Bitbucket项目管理工具(四) -- 安装bitbucket 5.7.0 安装Bitbucket的教程, 网上能找见的不多, ...

  9. 一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)

    一.MySQL中的索引###<1>索引的概念 索引就是一种数据结构(高效获取数据),在mysql中以文件的方式存在.存储建立了索引列的地址或者指向. 文件 :(以某种数据 结构存放) 存放 ...

随机推荐

  1. Lock,LockFree,MemoryBarrier,ConcurrentCollection

    最近看并行编程书本的一些心得,简单记录下多线程和并行编程必知必会的几个概念,再次加深自己的理解. .NET Framework4提供了一个新的命名空间System.Collections.Concur ...

  2. JS中的闭包

    在复习JS高程的过程中,在第七章闭包那节,发现自己看不太明白了.之前看高程的时候,都弄得挺清楚了,怎么现在反而又看不懂了. 嗯,也许更深层次的东西涉及到编译原理的知识了.嗯,在研究完SPA后就开始学习 ...

  3. lua的table表处理 及注意事项

    lua,一款很轻量级很nice很强大的脚本语言,做为lua中使用最为频繁的table表,在使用之时还是有颇多的好处与坑的: 下面是大牛 云风的一片关于lua table的blog,可使得对lua ta ...

  4. Atitit 面向对象弊端与问题 坏处 缺点

    Atitit 面向对象弊端与问题 坏处 缺点   1.1. 状态fsm,反模块化,又是反并行的,这是它的非常固有的特征, 1 1.2. 现时的OOP编程有可能不缓存友好(cache friendly) ...

  5. fir.im Weekly - 如何打造真正的工程师文化

    好的工程师,无法忍受低效且无趣的工作.优秀的技术团队应该自上而下的地推进技术平台化建设.DevOps.自动化构建.测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等. 先 ...

  6. js 优化

    一.for循环的优化 <!doctype html> <html lang="en"> <head> <meta charset=&quo ...

  7. KnockoutJS 3.X API 第四章 表单绑定(9) value绑定

    目的 value绑定主要用于DOM元素给视图模型赋值用的.通常用于<input><select><textarea>等元素. value绑定与text绑定的区别在于 ...

  8. CCNA网络工程师学习进程(5)路由器和交换机的登录安全配置和vlan划分

        本节详细介绍路由器和交换机的登录安全配置以及VLAN划分的原理.     (1)登录安全配置: 路由器登录有两种验证方式:有本地验证方式和远程验证方式.本地登录验证方式可以配置用户名和密码也可 ...

  9. c# BlowFish 高速 对称加密

    BlowFish 高速 对称加密 string key = "this is my key"; BlowFish algo = new BlowFish(key); string ...

  10. Uvaoj10054 - The Necklace

    /* 题意:打印欧拉回路! 思路:开始时不明白,dfs为什么是后序遍历? 因为欧拉回路本身是一条回路,那么我们在dfs时,可能存在提前找到回路,这条回路可能不是欧拉回路, 因为没有遍历完成所有的边!如 ...