C#使用BerkeleyDB操作简介
Berkeley DB是历史悠久的嵌入式数据库系统,主要应用在UNIX/LINUX操作系统上。Berkeley DB的存储的是key/value键值对,可以理解为硬盘上的超级hash表。其可以管理256TB数据,而且能支撑几千个并发访问。目前Berkeley DB有C++版和Java版。所以,我们需要一个访问的中间转换,已经有人发布了C#的API。可以从 Berkeley DB for .NET 上面找到,现在最新版是0.95版本,可以支持4.3和4.5版。本篇将以4.5版做实例。BerkeleyDB的版本可以在http://www.oracle.com/technology/products/berkeley-db/index.html下载,当前最新版本为4.7版。4.5 C++版的Berkeley DB可以在http://www.oracle.com/technology/software/products/berkeley-db/db/index.html这里下载。
By Birdshover@ 博客园 http://www.cnblogs.com/birdshover/
下载到Berkeley DB for .Net的API——libdb-dotnet_0_95.zip后,就可以开始使用了。首先在libdb-dotnet_0_95.zip解压缩的bin目录找到libdb_dotNET45.dll,这个就是4.5版本使用的dll。新建项目,引用这个dll。注意,自己编译源码可能会编译不过,主要是因为里面一些委托和委托的参数可见性不一致造成的。把那些参数用到的class 或者struct都调成public即可。
BerkeleyDB的数据库操作需要借助DbBTree类。因此需要先得到DbBTree的实例,但是DbBTree类会对其它几个类有依赖,必须依赖其它几个类才能创建。
下面代码就是初始化得到DbBTree实例的一个过程。
/// <summary>/// 数据库目录/// </summary> private string directory;/// <summary>/// 数据库文件名/// </summary> private string dbName; private DbBTree btree;private Txn txn;private Db db;private Env env;/// <summary>/// 初始化/// </summary> private void Init() { env = new Env(EnvCreateFlags.None); Env.OpenFlags envFlags = Env.OpenFlags.Create | Env.OpenFlags.InitLock | Env.OpenFlags.InitLog | Env.OpenFlags.InitMPool | Env.OpenFlags.InitTxn | Env.OpenFlags.Recover; env.Open(directory, envFlags, 0); txn = env.TxnBegin(null, Txn.BeginFlags.None); db = env.CreateDatabase(DbCreateFlags.None); btree = (DbBTree)db.Open(txn, dbName, null, DbType.BTree, Db.OpenFlags.Create, 0); }
另外Berkeley DB数据库的操作需要借助于序列化。
/// <summary>/// 二进制序列化/// </summary> private BinaryFormatter formatter;/// <summary>/// 键内存流/// </summary> private MemoryStream keyStream;/// <summary>/// 内容内存流/// </summary> private MemoryStream dataStream; private void StreamInit() { formatter = new BinaryFormatter(); keyStream = new MemoryStream(); dataStream = new MemoryStream(); }
public interface IPut {string Key { get; } }
public bool Set(IPut put) { Reset(); keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); dataStream.Position = 0; formatter.Serialize(dataStream, put); DbEntry data = DbEntry.InOut(dataStream.GetBuffer(), 0, (int)dataStream.Position); WriteStatus status = btree.Put(txn, ref key, ref data);switch (status) {case WriteStatus.Success:return true;case WriteStatus.NotFound:case WriteStatus.KeyExist:default:return false; } }
public bool Remove(IPut put) { keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); DeleteStatus status = btree.Delete(txn, ref key);switch (status) {case DeleteStatus.NotFound:case DeleteStatus.Success:return true;case DeleteStatus.KeyEmpty:default:return false; } }
private bool iscomit = false;public void Commit() { txn.Commit(Txn.CommitMode.None); iscomit = true; }
public bool Get(ref IPut put) { keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); dataStream.SetLength(dataStream.Capacity); DbEntry data = DbEntry.Out(dataStream.GetBuffer()); while (true) { ReadStatus status = btree.Get(txn, ref key, ref data, DbFile.ReadFlags.None); switch (status) {case ReadStatus.Success: dataStream.Position = 0; dataStream.SetLength(data.Size); put = (IPut)formatter.Deserialize(dataStream);return true;case ReadStatus.BufferSmall: //扩容 if (key.Buffer.Length < key.Size) { keyStream.SetLength(key.Size); key = DbEntry.Out(keyStream.GetBuffer()); }if (data.Buffer.Length < data.Size) { dataStream.SetLength(data.Size); data = DbEntry.Out(dataStream.GetBuffer()); }continue;case ReadStatus.NotFound:case ReadStatus.KeyEmpty:default:return false; } } }
public List<IPut> Find() { List<IPut> custList = new List<IPut>();using (DbBTreeCursor cursor = btree.OpenCursor(txn, DbFileCursor.CreateFlags.None)) { IPut cust = null;while (GetNextRecord(cursor, ref cust)) custList.Add(cust); }return custList; } private bool GetNextRecord(DbBTreeCursor cursor, ref IPut cust) { ReadStatus status; keyStream.SetLength(keyStream.Capacity); dataStream.SetLength(dataStream.Capacity); DbEntry key = DbEntry.Out(keyStream.GetBuffer()); DbEntry data = DbEntry.Out(dataStream.GetBuffer());do { status = cursor.Get(ref key, ref data, DbFileCursor.GetMode.Next, DbFileCursor.ReadFlags.None);switch (status) {case ReadStatus.NotFound: return false;case ReadStatus.KeyEmpty: continue; // skip deleted records case ReadStatus.BufferSmall:if (key.Buffer.Length < key.Size) { keyStream.SetLength(key.Size); key = DbEntry.Out(keyStream.GetBuffer()); }if (data.Buffer.Length < data.Size) { dataStream.SetLength(data.Size); data = DbEntry.Out(dataStream.GetBuffer()); }continue;case ReadStatus.Success: dataStream.Position = 0; dataStream.SetLength(data.Size); cust = (IPut)formatter.Deserialize(dataStream);return true;default:return false; } } while (true); }
代码:BerkeleyDB操作封装 public interface IPut {string Key { get; } } public class BDBManager : IDisposable {/// <summary>/// 数据库目录/// </summary> private string directory;/// <summary>/// 数据库文件名/// </summary> private string dbName; private DbBTree btree;private Txn txn;private Db db;private Env env; /// <summary>/// 二进制序列化/// </summary> private BinaryFormatter formatter;/// <summary>/// 键内存流/// </summary> private MemoryStream keyStream;/// <summary>/// 内容内存流/// </summary> private MemoryStream dataStream; public BDBManager(string directory, string dbName) {this.directory = directory;this.dbName = dbName; Init(); StreamInit(); } public bool Set(IPut put) { Reset(); keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); dataStream.Position = 0; formatter.Serialize(dataStream, put); DbEntry data = DbEntry.InOut(dataStream.GetBuffer(), 0, (int)dataStream.Position); WriteStatus status = btree.Put(txn, ref key, ref data);switch (status) {case WriteStatus.Success:return true;case WriteStatus.NotFound:case WriteStatus.KeyExist:default:return false; } } private bool iscomit = false;public void Commit() { txn.Commit(Txn.CommitMode.None); iscomit = true; } public List<IPut> Find() { List<IPut> custList = new List<IPut>();using (DbBTreeCursor cursor = btree.OpenCursor(txn, DbFileCursor.CreateFlags.None)) { IPut cust = null;while (GetNextRecord(cursor, ref cust)) custList.Add(cust); }return custList; } public bool Get(ref IPut put) { keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); dataStream.SetLength(dataStream.Capacity); DbEntry data = DbEntry.Out(dataStream.GetBuffer()); while (true) { ReadStatus status = btree.Get(txn, ref key, ref data, DbFile.ReadFlags.None); switch (status) {case ReadStatus.Success: dataStream.Position = 0; dataStream.SetLength(data.Size); put = (IPut)formatter.Deserialize(dataStream);return true;case ReadStatus.BufferSmall: //扩容 if (key.Buffer.Length < key.Size) { keyStream.SetLength(key.Size); key = DbEntry.Out(keyStream.GetBuffer()); }if (data.Buffer.Length < data.Size) { dataStream.SetLength(data.Size); data = DbEntry.Out(dataStream.GetBuffer()); }continue;case ReadStatus.NotFound:case ReadStatus.KeyEmpty:default:return false; } } } public bool Remove(IPut put) { Reset(); keyStream.Position = 0; formatter.Serialize(keyStream, put.Key); DbEntry key = DbEntry.InOut(keyStream.GetBuffer(), 0, (int)keyStream.Position); DeleteStatus status = btree.Delete(txn, ref key);switch (status) {case DeleteStatus.NotFound:case DeleteStatus.Success:return true;case DeleteStatus.KeyEmpty:default:return false; } } public void Dispose() {if (!iscomit) Commit(); db.Close(); db.Close(); } private void Reset() { iscomit = false; } private void Init() { env = new Env(EnvCreateFlags.None); Env.OpenFlags envFlags = Env.OpenFlags.Create | Env.OpenFlags.InitLock | Env.OpenFlags.InitLog | Env.OpenFlags.InitMPool | Env.OpenFlags.InitTxn | Env.OpenFlags.Recover; env.Open(directory, envFlags, 0); txn = env.TxnBegin(null, Txn.BeginFlags.None); db = env.CreateDatabase(DbCreateFlags.None); btree = (DbBTree)db.Open(txn, dbName, null, DbType.BTree, Db.OpenFlags.Create, 0); } private void StreamInit() { formatter = new BinaryFormatter(); keyStream = new MemoryStream(); dataStream = new MemoryStream(); } private bool GetNextRecord(DbBTreeCursor cursor, ref IPut cust) { ReadStatus status; keyStream.SetLength(keyStream.Capacity); dataStream.SetLength(dataStream.Capacity); DbEntry key = DbEntry.Out(keyStream.GetBuffer()); DbEntry data = DbEntry.Out(dataStream.GetBuffer());do { status = cursor.Get(ref key, ref data, DbFileCursor.GetMode.Next, DbFileCursor.ReadFlags.None);switch (status) {case ReadStatus.NotFound: return false;case ReadStatus.KeyEmpty: continue; // skip deleted records case ReadStatus.BufferSmall:if (key.Buffer.Length < key.Size) { keyStream.SetLength(key.Size); key = DbEntry.Out(keyStream.GetBuffer()); }if (data.Buffer.Length < data.Size) { dataStream.SetLength(data.Size); data = DbEntry.Out(dataStream.GetBuffer()); }continue;case ReadStatus.Success: dataStream.Position = 0; dataStream.SetLength(data.Size); cust = (IPut)formatter.Deserialize(dataStream);return true;default:return false; } } while (true); } }
[Serializable()]class Item : IPut {public string Name { get; set; }public string Text { get; set; }public int ID { get; set; } public override string ToString() {return string.Format("ID:{0} Key:{1}", ID, Name); } public string Key {get { return Name; } } }
using (BDBManager manager = new BDBManager("db", "db.dat")) {bool success = manager.Set(new Item() { ID = 1000, Name = "Test",Text = "213" }); Console.WriteLine(string.Format("set is {0}", success)); } using (BDBManager manager = new BDBManager("db", "db.dat")) { IPut put = new Item() { Name = "Test" };bool success = manager.Get(ref put); Console.WriteLine(string.Format("read is {0},item : {1}", success, put.ToString())); } using (BDBManager manager = new BDBManager("db", "db.dat")) { IPut put = new Item() { Name = "Test" };bool success = manager.Remove(put); Console.WriteLine(string.Format("remove is {0},item : {1}", success, put.ToString())); } using (BDBManager manager = new BDBManager("db", "db.dat")) { List<IPut> list = manager.Find();foreach (var item in list) { Console.WriteLine(item.ToString()); } } Console.WriteLine("end"); Console.ReadKey();
C#使用BerkeleyDB操作简介相关推荐
- python中常见的流程结构-Python分支结构(switch)操作简介
Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...
- python分支switch_Python分支结构(switch)操作简介
Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...
- python中分支结构包括哪些_Python分支结构(switch)操作简介
Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...
- oracle kepserve,Kepware.KEPServer\KEPServerEX_V5操作简介含opc quick client 连接测试
[实例简介] Kepware.KEPServer\KEPServerEX_V5操作简介含opc quick client 连接测试 3.開魯 KEPServereX的管理視窗 請從「開始」->「 ...
- 作业一:数据软件系统的介绍及spss的操作简介
数据分析软件介绍 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程.这一过程也是质量管理体系的支持过程.在实用中, ...
- JMeter入门操作简介
JMeter入门操作简介 1.JMter简介及作用 JMter是Apache公司用Java开发的一款测试工具 接口测试.性能测试.数据库测试.java程序测试. 可以对服务器.网络或者对象模拟巨大的负 ...
- UE官方教程笔记03-功能、术语、操作简介
对官方教程视频[官方培训]03-UE功能.术语.操作简介 | 徐良安 Epic的笔记 这一部分基本都是走马观花的简单介绍 功能 世界创建 建模 Mesh editingtool是一个全新的建模工具,具 ...
- stm32 HAL库 Flash操作简介
stm32 HAL库 Flash操作简介 目录 第一stm32,flash介绍 查看代码段,以判断代码长度 flash的基本操作规则 stm32 HAL库 Flash操作指南 stm32f1xx_ha ...
- Python|并发编程|爬虫|单线程|多线程|异步I/O|360图片|Selenium及JavaScript|Scrapy框架|BOM 和 DOM 操作简介|语言基础50课:学习(12)
文章目录 系列目录 原项目地址 第37课:并发编程在爬虫中的应用 单线程版本 多线程版本 异步I/O版本 总结 第38课:抓取网页动态内容 Selenium 介绍 使用Selenium 加载页面 查找 ...
最新文章
- len()与cap()的区别
- 2019级C语言大作业 - 十步万度
- 斐波那契数列基本性质
- 部署Screego浏览器实现多人共享屏幕
- hybird app
- python抽奖程序_抽奖程序python
- 你必须知道的 NET(第2版)
- 关于maven-jdocbook-plugin插件org.jboss.highlight.XhtmlRendererFactory does not indentify an extern的一个小问题
- WordPress优化教程大全
- react与mobx搭配时如何缓存mobx的数据(刷新之后保存状态)
- Jenkins 插件开发记录
- Centos 7 Authorization failed. Make sure polkit agent is running or run the application as superuser
- POJ1845 数论
- IDEA中,写代码在中间插入字符时会把后面的字符覆盖掉
- stm32miniRTC实时时钟——HAL库
- 【雕爷学编程】Arduino动手做(101)---12位智能RGB彩环
- 上千数据指标,如何1周开发完?
- 五百丁-ppt模板-创业融资-top45 下载
- 综合实验 电子记事本的设计与实现——Java
- flash小黄油安卓_这是第一台安卓手机,当年谷歌和 HTC 靠它正面刚苹果极客博物馆...
热门文章
- 网上的python教程值不值得买_Python新人入手线程技术教程,值得收藏
- list group by java_Java List集合实现MySQL Group By功能
- python中常见的数据类型_Python中常见的数据类型总结(四)
- Java 组合模式及其应用
- 宁波工程学院2020新生校赛(重现赛)部分题解
- 图论500题 ---- (枚举+并查集)求图上路径权值差值最小 HDU find the most comfortable road
- Educational Codeforces Round 84 (Rated for Div. 2) A~ ESZU cf集训
- html input type=quot;filequot;,科技常识:关于type=quot;filequot;的input框样式修改小结...
- c++把数组所有元素剔除_C语言基础之数组,第一节,C语言必学知识点剖析
- htc one m7刷Linux,HTC One M7刷机教程 HTC One M7线刷教程