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();
    
    
    
    
  • 相关阅读:
    三大主流负载均衡软件对比(LVS+Nginx+HAproxy)
    nginx 提示the "ssl" directive is deprecated, use the "listen ... ssl" directive instead
    centos安装nginx并配置SSL证书
    hadoop创建目录文件失败
    The server time zone value 'EDT' is unrecognized or represents more than one time zone.
    脚本启动SpringBoot(jar)
    centos做免密登录
    数据库远程连接配置
    Bash 快捷键
    TCP三次握手四次断开
  • 原文地址:https://www.cnblogs.com/birdshover/p/1305743.html
Copyright © 2011-2022 走看看