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();        }

Berkeley DB是键值数据库,因此定义一个获取键接口:
    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;            }        }

三、关于添加和删除
添加和删除并没有真正得进行添加和删除。必须执行Commit操作:
        private bool iscomit = false;public void Commit()        {            txn.Commit(Txn.CommitMode.None);            iscomit = true;        }

四、寻找键
用键查询值,和hash表一样使用。
        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);        }    }

调用方法:
首先要有一个写入的实体类,必须可以序列化,并且实现IPut接口:
        [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操作简介相关推荐

  1. python中常见的流程结构-Python分支结构(switch)操作简介

    Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...

  2. python分支switch_Python分支结构(switch)操作简介

    Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...

  3. python中分支结构包括哪些_Python分支结构(switch)操作简介

    Python当中并无switch语句,本文研究的主要是通过字典实现switch语句的功能,具体如下. switch语句用于编写多分支结构的程序,类似与if-.elif-.else语句. switch语 ...

  4. oracle kepserve,Kepware.KEPServer\KEPServerEX_V5操作简介含opc quick client 连接测试

    [实例简介] Kepware.KEPServer\KEPServerEX_V5操作简介含opc quick client 连接测试 3.開魯 KEPServereX的管理視窗 請從「開始」->「 ...

  5. 作业一:数据软件系统的介绍及spss的操作简介

        数据分析软件介绍     数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程.这一过程也是质量管理体系的支持过程.在实用中, ...

  6. JMeter入门操作简介

    JMeter入门操作简介 1.JMter简介及作用 JMter是Apache公司用Java开发的一款测试工具 接口测试.性能测试.数据库测试.java程序测试. 可以对服务器.网络或者对象模拟巨大的负 ...

  7. UE官方教程笔记03-功能、术语、操作简介

    对官方教程视频[官方培训]03-UE功能.术语.操作简介 | 徐良安 Epic的笔记 这一部分基本都是走马观花的简单介绍 功能 世界创建 建模 Mesh editingtool是一个全新的建模工具,具 ...

  8. stm32 HAL库 Flash操作简介

    stm32 HAL库 Flash操作简介 目录 第一stm32,flash介绍 查看代码段,以判断代码长度 flash的基本操作规则 stm32 HAL库 Flash操作指南 stm32f1xx_ha ...

  9. Python|并发编程|爬虫|单线程|多线程|异步I/O|360图片|Selenium及JavaScript|Scrapy框架|BOM 和 DOM 操作简介|语言基础50课:学习(12)

    文章目录 系列目录 原项目地址 第37课:并发编程在爬虫中的应用 单线程版本 多线程版本 异步I/O版本 总结 第38课:抓取网页动态内容 Selenium 介绍 使用Selenium 加载页面 查找 ...

最新文章

  1. len()与cap()的区别
  2. 2019级C语言大作业 - 十步万度
  3. 斐波那契数列基本性质
  4. 部署Screego浏览器实现多人共享屏幕
  5. hybird app
  6. python抽奖程序_抽奖程序python
  7. 你必须知道的 NET(第2版)
  8. 关于maven-jdocbook-plugin插件org.jboss.highlight.XhtmlRendererFactory does not indentify an extern的一个小问题
  9. WordPress优化教程大全
  10. react与mobx搭配时如何缓存mobx的数据(刷新之后保存状态)
  11. Jenkins 插件开发记录
  12. Centos 7 Authorization failed. Make sure polkit agent is running or run the application as superuser
  13. POJ1845 数论
  14. IDEA中,写代码在中间插入字符时会把后面的字符覆盖掉
  15. stm32miniRTC实时时钟——HAL库
  16. 【雕爷学编程】Arduino动手做(101)---12位智能RGB彩环
  17. 上千数据指标,如何1周开发完?
  18. 五百丁-ppt模板-创业融资-top45 下载
  19. 综合实验 电子记事本的设计与实现——Java
  20. flash小黄油安卓_这是第一台安卓手机,当年谷歌和 HTC 靠它正面刚苹果极客博物馆...

热门文章

  1. 网上的python教程值不值得买_Python新人入手线程技术教程,值得收藏
  2. list group by java_Java List集合实现MySQL Group By功能
  3. python中常见的数据类型_Python中常见的数据类型总结(四)
  4. Java 组合模式及其应用
  5. 宁波工程学院2020新生校赛(重现赛)部分题解
  6. 图论500题 ---- (枚举+并查集)求图上路径权值差值最小 HDU find the most comfortable road
  7. Educational Codeforces Round 84 (Rated for Div. 2) A~ ESZU cf集训
  8. html input type=quot;filequot;,科技常识:关于type=quot;filequot;的input框样式修改小结...
  9. c++把数组所有元素剔除_C语言基础之数组,第一节,C语言必学知识点剖析
  10. htc one m7刷Linux,HTC One M7刷机教程 HTC One M7线刷教程