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

对于一般的个人迷你项目,数据量不大的时候,完全没有必要使用数据库,管理数据使用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);
}

出处:https://www.cnblogs.com/TextEditor/p/4195361.html

完整代码参考:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml; namespace ConsoleApplication1.xml
{
/// <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>
List<Model<T>> list = new List<Model<T>>(); /// <summary>
/// 数据库文件
/// </summary>
string DBfilename = string.Empty; /// <summary>
/// 数据库状态
/// </summary>
public string Status = "Close"; /// <summary>
/// 数据库记录数[Without IsDel]
/// </summary>
/// <returns></returns>
public int getCountWithoutDel()
{
Refresh();
return list.Count(x => !x.IsDel); } /// <summary>
/// 数据库记录数[With All]
/// </summary>
/// <returns></returns>
public int getCountWithAll()
{
Refresh();
return list.Count;
} /// <summary>
/// 新建并且打开数据库
/// </summary>
/// <param name="xmlfilename"></param>
public XmlDataBase(string xmlfilename)
{
DBfilename = xmlfilename;
if (System.IO.File.Exists(DBfilename))
{
list = LoadObjFromXml<List<Model<T>>>(DBfilename);
}
} /// <summary>
/// 刷新数据
/// </summary>
public void Refresh()
{
//非静态,所以,可能在其他地方发生了数据更新
if (System.IO.File.Exists(DBfilename))
{
list = LoadObjFromXml<List<Model<T>>>(DBfilename);
}
} /// <summary>
/// 压缩数据库,清理已经删除的记录
/// </summary>
public void Compress()
{
var Compresslist = new List<Model<T>>();
Func<Model<T>, Boolean> inner = (x) => (!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 = DeepCopy(rec);
dbrec.LastUpdate = DateTime.Now;
list.Add(dbrec);
} /// <summary>
/// 删除
/// </summary>
/// <param name="rec"></param>
public void DelRecord(Model<T> rec)
{
rec.IsDel = true;
UpdateDB(DeepCopy(rec));
} /// <summary>
/// 删除制定编号数据
/// </summary>
/// <param name="DBId"></param>
public void DelRecordByDBID(string DBId)
{
for (int i = ; i < list.Count; i++)
{
if (DBId == list[i].DBId)
{
list[i].IsDel = true;
list[i].LastUpdate = DateTime.Now;
break;
}
}
} /// <summary>
/// 更新
/// </summary>
/// <param name="rec"></param>
public void UpdataRec(Model<T> rec)
{
UpdateDB(DeepCopy(rec));
} /// <summary>
/// 数据的修改
/// </summary>
/// <param name="rec">传递过来对象的深拷贝</param>
private 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()
{
SaveObjAsXml(DBfilename, list);
} /// <summary>
/// 检索
/// </summary>
/// <param name="SearchMethod"></param>
/// <returns>数据对象的深拷贝</returns>
public List<Model<T>> SearchAsDBRecords(Func<T, Boolean> SearchMethod)
{
Refresh();
Func<Model<T>, Boolean> inner = (x) => (SearchMethod(x.DataRec) && !x.IsDel);
var t = new List<Model<T>>();
foreach (Model<T> element in list.FindAll(new Predicate<Model<T>>(inner)))
{
//这里也是将数据的副本给与外部
t.Add(DeepCopy(element));
}
return t;
} /// <summary>
/// 检索(根据数据号)
/// </summary>
/// <param name="DBID">数据号</param>
/// <returns></returns>
public Model<T> SearchAsDBRecordByDBID(string DBID)
{
Refresh();
Model<T> result = list.Find((x) => x.DBId == DBID && !x.IsDel);
if (result != null)
return DeepCopy(result);
return null;
} /// <summary>
/// 检索,(如果只是获取T对象列表)
/// </summary>
/// <param name="SearchMethod"></param>
/// <returns>数据对象的深拷贝</returns>
public List<T> SearchAsObjRecords(Func<T, Boolean> SearchMethod)
{
Refresh();
Func<Model<T>, Boolean> inner = (x) => (SearchMethod(x.DataRec) && !x.IsDel);
var t = new List<T>();
foreach (Model<T> element in list.FindAll(new Predicate<Model<T>>(inner)))
{
//这里也是将数据的副本给与外部
t.Add(DeepCopy(element.DataRec));
}
return t;
} /// <summary>
/// 检索(根据数据号)(如果只是获取T对象)
/// 调用前请使用IsRecordExist函数确认数据是否存在
/// </summary>
/// <param name="DBID">数据号</param>
/// <returns></returns>
public T SearchAsObjRecordByDBID(string DBID)
{
Refresh();
T t = default(T);
Model<T> result = list.Find((x) => x.DBId == DBID);
t =DeepCopy(result.DataRec);
return t;
} /// <summary>
/// 是否存在数据
/// </summary>
/// <param name="SearchMethod"></param>
/// <returns></returns>
public bool IsRecordExists(Func<T, Boolean> SearchMethod)
{
Func<Model<T>, Boolean> inner = (x) => (SearchMethod(x.DataRec) && !x.IsDel);
return list.FindAll(new Predicate<Model<T>>(inner)).Count != ;
} /// <summary>
/// 是否存在指定番号数据
/// </summary>
/// <param name="DBID"></param>
/// <returns></returns>
public bool IsRecordExistsByDBID(string DBID)
{
Func<Model<T>, Boolean> inner = (x) => (x.DBId == DBID && !x.IsDel);
return list.FindAll(new Predicate<Model<T>>(inner)).Count != ;
} /// <summary>
/// 保存对象
/// </summary>
/// <param name="filename"></param>
/// <param name="Obj"></param>
private static void SaveObjAsXml<T>(string filename, T Obj)
{
var settings = new XmlWriterSettings();
settings.Indent = true;
//NewLineChars对于String属性的东西无效
//这是对于XML中换行有效,
//String的换行会变成Console的NewLine /n
settings.NewLineChars = System.Environment.NewLine;
var xml = new XmlSerializer(typeof(T));
var writer = XmlWriter.Create(filename, settings);
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
xml.Serialize(writer, Obj, ns);
writer.Close();
} /// <summary>
/// 读取对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filename"></param>
/// <returns></returns>
private static T LoadObjFromXml<T>(string filename)
{
var setting = new XmlReaderSettings();
var xml = new XmlSerializer(typeof(T));
var reader = XmlReader.Create(filename, setting);
T obj = (T)xml.Deserialize(reader);
reader.Close();
return obj;
} /// <summary>
/// 深拷贝
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static T DeepCopy<T>(T obj)
{
var bFormatter = new BinaryFormatter();
var stream = new MemoryStream();
bFormatter.Serialize(stream, obj);
stream.Seek(, SeekOrigin.Begin);
return (T)bFormatter.Deserialize(stream);
}
}
}

对象定义格式如下:

// 模式一

using System;
namespace ConsoleApplication1.xml
{
/// <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>
public Boolean Search(string strKeyword)
{
return false;
} }
} // 模式二
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleApplication1.xml
{
[Serializable]
public class CodeBook
{
private string bName; public string BookName
{
get { return bName; }
set { bName = value; }
} private string bAnthor; public string Anthor
{
get { return bAnthor; }
set { bAnthor = value; }
} private int _price; public int Price
{
get { return _price; }
set { _price = value; }
} }
}

调用方式参考:

            xml.XmlDataBase<xml.CodeSnap> db = new xml.XmlDataBase<xml.CodeSnap>(@"C:\temp\CodeSnap.xml");
for (int i = ; i < ; i++)
{
var r = new xml.CodeSnap();
r.Title = "Title" + i.ToString();
r.Descrpition = "Descrpition";
r.Tag = "Tag";
r.Code = "Code";
db.AppendRec(r);
}
//db.Commit(); xml.XmlDataBase<xml.CodeBook> db1 = new xml.XmlDataBase<xml.CodeBook>(@"C:\temp\book.xml");
for (int i = ; i < ; i++)
{
var r = new xml.CodeBook();
r.Anthor = "anth " + i;
r.BookName = " book " + i;
r.Price = i;
db1.AppendRec(r);
}
//db1.Commit(); var t = db1.SearchAsDBRecords((m) =>
{
return true;
}); var bbb = t.FindAll((ss) => {return ss.DataRec.Price > ;}); for (int i = ; i < t.Count; i++)
{
if (i % == )
{
//xml.CodeBook b = t[i];
//t[i].Price += 10;
t[i].DataRec.Price += ;
//db1.UpdataRec(t[i]);
}
if (i==)
{
//db1.DelRecordByDBID(t[i].DBId);
db1.DelRecord(t[i]);
}
Console.WriteLine(db1.Status);
}
db1.Commit();
Console.WriteLine(db1.getCountWithAll());
db1.Compress();

XML数据库的尝试的更多相关文章

  1. 提高生产性工具(四) - XML数据库的尝试

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

  2. 基于XML数据库的学生信息管理系统的设计与实现

    本项目是在学习之余写的,主要用来练习MVC+DAO的分层设计思想,项目基于一个简单的XML学生数据库,使用XML作为数据库的原因是其十分的小巧与方便,使用dom4j即可进行方便的解析.因为这段时间课程 ...

  3. 转载unity编辑器xml数据库插件

    unity编辑器xml数据库插件 注:9月9日更新,其中MyXML.cs中有一句代码写错,查找功能失误,文中已经修改! 注:9月1日更新说明:xml存储结构,因为在用xml之前不知道正规的xml数据结 ...

  4. 关于VS连接Oracle数据库提示:“尝试加载oracle客户端时引发badimage,如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题”的解决方案。

    错误一.关于VS连接Oracle数据库提示:“尝试加载oracle客户端时引发badimage,如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题”的解决方案. ...

  5. 一个C#的XML数据库访问类

    原文地址:http://hankjin.blog.163.com/blog/static/33731937200942915452244/ 程序中不可避免的要用到配置文件或数据,对于数据量比较小的程序 ...

  6. 简单的xml数据库设计

    我的需求 有时候系统需要存储一些简单的关系型属性,不考虑并发,不考虑性能(一次操作在几ms),数据库没有其他依赖引用,拿过来就可以用 为什么选xml作为数据库? 可读性好 实体的对应关系不严格 , 二 ...

  7. 使用MongoDB作为后台数据库的尝试

    MongoDB作为一个阶层型数据库,在很短的时间里面是不可能被大面积推广使用的, 本文作为一个实验性的课题,探讨一下MongoDB作为网站数据库的可能性. 1.MongoDB作为代替关系型数据库的可能 ...

  8. 新入门PGSQL数据库(尝试利用PGPOOL实现分布式),摘录笔记

    概念: PostgreSQL (pronounced "post-gress-Q-L") is an open source relational database managem ...

  9. 微信小程序开发 (资料汇总,谁还没被坑过?希望助你绕过一些坑)

    最近帮人家做一个微信小程序,刚好想熟悉一下.由于牵扯到多用户使用系统,以及数据共享,所以自然架构选择了,客户端和服务器的方式. 后台服务器是windows server,后台程序是.Net  WebA ...

随机推荐

  1. OC自动释放池autoreleasepool介绍

    自动释放池的机制是:它使得应用在创建新对象时,系统能够有效地管理应用所使用的内存. @autoreleasepool { statements } 在创建新对象时,并且系统未启动ARC特性,那么在使用 ...

  2. lambda可调用对象

    //find_if谓词使用 bool isShorter(const string &s1, const string &sz){ return s1.size() < sz.s ...

  3. lelel-5

    一.样式有几种引入方式?link和@import有什么区别? 样式有3种引入方式: 外部样式(外联式Linking):是将网页链接到外部样式表<link rel="stylesheet ...

  4. blast+学习之search tools

    search tools:blastn, blastp, blastx, tblastx, tblastn, psiblast, rpsblast, and rpstblastn 1.blastn: ...

  5. FreeBSD 安装过程

    FreeBSD安装步骤: 回车 按默认回车 输入服务器的计算机名 去掉games,加上src安装如下图 Lib32 ports src这三项一定要安装上 回车 选择Manual 进入以后点create ...

  6. Shell脚本实现SSH免密登录及批量配置管理

    本节索引 场景分析 ssh免密登录 pssh工具批量管理 SHELL自动化脚本 本篇总结 场景分析 作为一个运维工程师,不是每个人工作的环境都想阿里.腾讯那样,动不动就上亿的PV量,上万台服务器.我们 ...

  7. 使用Homebrew管理你的mac开发包

    很多人可能不了解 Homebrew, 其实它相当于开发软件界的 Appstore. 比如,如果我要安装 python 的最新版本,那么传统的做法是 1. 到官方网站下载 python 的最新版本 2. ...

  8. Flume具体应用(多案例)

    日志采集 对于flume的原理其实很容易理解,我们更应该掌握flume的具体使用方法,flume提供了大量内置的Source.Channel和Sink类型.而且不同类型的Source.Channel和 ...

  9. UVA 11029 || Lightoj 1282 Leading and Trailing 数学

    Leading and Trailing You are given two integers: n and k, your task is to find the most significant ...

  10. 2017-02-23 错误信息:未在本地计算机上注册“Microsoft.ACE.oledb.12.0”提供程序。

    问题如题,解决办法:去 http://download.microsoft.com/download/7/0/3/703ffbcb-dc0c-4e19-b0da-1463960fdcdb/Access ...