zoukankan      html  css  js  c++  java
  • 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();
    }
    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操作封装
    调用方法:
    首先要有一个写入的实体类,必须可以序列化,并且实现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();
    
    
    
    
  • 相关阅读:
    自定义checkbox样式
    自定义select样式
    jsonp
    I/O复用 poll简介
    DOS和DDOS攻击
    TCP状态转换图解析
    Makefile入门
    I/O复用select 使用简介
    替换文本内容
    share memory
  • 原文地址:https://www.cnblogs.com/birdshover/p/1305743.html
Copyright © 2011-2022 走看看