熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#使用BerkeleyDB操作簡介

2013-11-13 10:02:14  來源: .NET編程 
  Berkeley DB是歷史悠久的嵌入式數據庫系統主要應用在UNIX/LINUX操作系統上Berkeley DB的存儲的是key/value鍵值對可以理解為硬盤上的超級hash表其可以管理TB數據而且能支撐幾千個並發訪問目前Berkeley DB有C++版和Java版所以我們需要一個訪問的中間轉換已經有人發布了C#的API可以從 Berkeley DB for NET 上面找到現在最新版是版本可以支持本篇將以版做實例BerkeleyDB的版本可以在db/l下載當前最新版本為 C++版的Berkeley DB可以在db/db/l這裡下載
  
   By Birdshover@ 博客園
  
  下載到Berkeley DB for Net的API——libdbdotnet__zip後就可以開始使用了首先在libdbdotnet__zip解壓縮的bin目錄找到libdb_dotNETdll這個就是版本使用的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(EnvCreateFlagsNone);
   EnvOpenFlags envFlags =
   EnvOpenFlagsCreate |
   EnvOpenFlagsInitLock |
   EnvOpenFlagsInitLog |
   EnvOpenFlagsInitMPool |
   EnvOpenFlagsInitTxn |
   EnvOpenFlagsRecover;
   envOpen(directory envFlags );
   txn = envTxnBegin(null TxnBeginFlagsNone);
   db = envCreateDatabase(DbCreateFlagsNone);
   btree = (DbBTree)dbOpen(txn dbName null DbTypeBTree DbOpenFlagsCreate );
   }
  
  
  另外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();
  
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   dataStreamPosition = ;
   formatterSerialize(dataStream put);
   DbEntry data = DbEntryInOut(dataStreamGetBuffer() (int)dataStreamPosition);
   WriteStatus status = btreePut(txn ref key ref data);
   switch (status)
   {
   case WriteStatusSuccess:
   return true;
   case WriteStatusNotFound:
   case WriteStatusKeyExist:
   default:
   return false;
   }
   }
  上述代碼就可以保存鍵值顯示對鍵值進行序列化然後再保存保存完有三個狀態可以一一處理
  二數據庫的刪除
  刪除最為簡單
   public bool Remove(IPut put)
   {
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   DeleteStatus status = btreeDelete(txn ref key);
   switch (status)
   {
   case DeleteStatusNotFound:
   case DeleteStatusSuccess:
   return true;
   case DeleteStatusKeyEmpty:
   default:
   return false;
   }
   }
  三關於添加和刪除
  添加和刪除並沒有真正得進行添加和刪除必須執行Commit操作
   private bool iscomit = false;
   public void Commit()
   {
   txnCommit(TxnCommitModeNone);
   iscomit = true;
   }
  四尋找鍵
  用鍵查詢值和hash表一樣使用
   public bool Get(ref IPut put)
   {
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   dataStreamSetLength(dataStreamCapacity);
   DbEntry data = DbEntryOut(dataStreamGetBuffer());
  
   while (true)
   {
   ReadStatus status = btreeGet(txn ref key ref data DbFileReadFlagsNone);
  
   switch (status)
   {
   case ReadStatusSuccess:
   dataStreamPosition = ;
   dataStreamSetLength(dataSize);
   put = (IPut)formatterDeserialize(dataStream);
   return true;
   case ReadStatusBufferSmall: //擴容
   if (keyBufferLength < keySize)
   {
   keyStreamSetLength(keySize);
   key = DbEntryOut(keyStreamGetBuffer());
   }
   if (dataBufferLength < dataSize)
   {
   dataStreamSetLength(dataSize);
   data = DbEntryOut(dataStreamGetBuffer());
   }
   continue;
   case ReadStatusNotFound:
   case ReadStatusKeyEmpty:
   default:
   return false;
   }
   }
   }
  五遍歷
  public List<IPut> Find()
   {
   List<IPut> custList = new List<IPut>();
   using (DbBTreeCursor cursor = btreeOpenCursor(txn DbFileCursorCreateFlagsNone))
   {
   IPut cust = null;
   while (GetNextRecord(cursor ref cust))
   custListAdd(cust);
   }
   return custList;
   }
  
   private bool GetNextRecord(DbBTreeCursor cursor ref IPut cust)
   {
   ReadStatus status;
   keyStreamSetLength(keyStreamCapacity);
   dataStreamSetLength(dataStreamCapacity);
   DbEntry key = DbEntryOut(keyStreamGetBuffer());
   DbEntry data = DbEntryOut(dataStreamGetBuffer());
   do
   {
   status = cursorGet(ref key ref data DbFileCursorGetModeNext DbFileCursorReadFlagsNone);
   switch (status)
   {
   case ReadStatusNotFound: return false;
   case ReadStatusKeyEmpty: continue; // skip deleted records
   case ReadStatusBufferSmall:
   if (keyBufferLength < keySize)
   {
   keyStreamSetLength(keySize);
   key = DbEntryOut(keyStreamGetBuffer());
   }
   if (dataBufferLength < dataSize)
   {
   dataStreamSetLength(dataSize);
   data = DbEntryOut(dataStreamGetBuffer());
   }
   continue;
   case ReadStatusSuccess:
   dataStreamPosition = ;
   dataStreamSetLength(dataSize);
   cust = (IPut)formatterDeserialize(dataStream);
   return true;
   default:
   return false;
   }
   } while (true);
   }
  六完整操作封裝
  
   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)
   {
   thisdirectory = directory;
   thisdbName = dbName;
  
   Init();
   StreamInit();
   }
  
   public bool Set(IPut put)
   {
   Reset();
  
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   dataStreamPosition = ;
   formatterSerialize(dataStream put);
   DbEntry data = DbEntryInOut(dataStreamGetBuffer() (int)dataStreamPosition);
   WriteStatus status = btreePut(txn ref key ref data);
   switch (status)
   {
   case WriteStatusSuccess:
   return true;
   case WriteStatusNotFound:
   case WriteStatusKeyExist:
   default:
   return false;
   }
   }
  
   private bool iscomit = false;
   public void Commit()
   {
   txnCommit(TxnCommitModeNone);
   iscomit = true;
   }
  
   public List<IPut> Find()
   {
   List<IPut> custList = new List<IPut>();
   using (DbBTreeCursor cursor = btreeOpenCursor(txn DbFileCursorCreateFlagsNone))
   {
   IPut cust = null;
   while (GetNextRecord(cursor ref cust))
   custListAdd(cust);
   }
   return custList;
   }
  
   public bool Get(ref IPut put)
   {
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   dataStreamSetLength(dataStreamCapacity);
   DbEntry data = DbEntryOut(dataStreamGetBuffer());
  
   while (true)
   {
   ReadStatus status = btreeGet(txn ref key ref data DbFileReadFlagsNone);
  
   switch (status)
   {
   case ReadStatusSuccess:
   dataStreamPosition = ;
   dataStreamSetLength(dataSize);
   put = (IPut)formatterDeserialize(dataStream);
   return true;
   case ReadStatusBufferSmall: //擴容
   if (keyBufferLength < keySize)
   {
   keyStreamSetLength(keySize);
   key = DbEntryOut(keyStreamGetBuffer());
   }
   if (dataBufferLength < dataSize)
   {
   dataStreamSetLength(dataSize);
   data = DbEntryOut(dataStreamGetBuffer());
   }
   continue;
   case ReadStatusNotFound:
   case ReadStatusKeyEmpty:
   default:
   return false;
   }
   }
   }
  
   public bool Remove(IPut put)
   {
   Reset();
  
   keyStreamPosition = ;
   formatterSerialize(keyStream putKey);
   DbEntry key = DbEntryInOut(keyStreamGetBuffer() (int)keyStreamPosition);
   DeleteStatus status = btreeDelete(txn ref key);
   switch (status)
   {
   case DeleteStatusNotFound:
   case DeleteStatusSuccess:
   return true;
   case DeleteStatusKeyEmpty:
   default:
   return false;
   }
   }
  
   public void Dispose()
   {
   if (!iscomit)
   Commit();
   dbClose();
   dbClose();
   }
  
   private void Reset()
   {
   iscomit = false;
   }
  
   private void Init()
   {
   env = new Env(EnvCreateFlagsNone);
   EnvOpenFlags envFlags =
   EnvOpenFlagsCreate |
   EnvOpenFlagsInitLock |
   EnvOpenFlagsInitLog |
   EnvOpenFlagsInitMPool |
   EnvOpenFlagsInitTxn |
   EnvOpenFlagsRecover;
   envOpen(directory envFlags );
   txn = envTxnBegin(null TxnBeginFlagsNone);
   db = envCreateDatabase(DbCreateFlagsNone);
   btree = (DbBTree)dbOpen(txn dbName null DbTypeBTree DbOpenFlagsCreate );
   }
  
   private void StreamInit()
   {
   formatter = new BinaryFormatter();
   keyStream = new MemoryStream();
   dataStream = new MemoryStream();
   }
  
   private bool GetNextRecord(DbBTreeCursor cursor ref IPut cust)
   {
   ReadStatus status;
   keyStreamSetLength(keyStreamCapacity);
   dataStreamSetLength(dataStreamCapacity);
   DbEntry key = DbEntryOut(keyStreamGetBuffer());
   DbEntry data = DbEntryOut(dataStreamGetBuffer());
   do
   {
   status = cursorGet(ref key ref data DbFileCursorGetModeNext DbFileCursorReadFlagsNone);
   switch (status)
   {
   case ReadStatusNotFound: return false;
   case ReadStatusKeyEmpty: continue; // skip deleted records
   case ReadStatusBufferSmall:
   if (keyBufferLength < keySize)
   {
   keyStreamSetLength(keySize);
   key = DbEntryOut(keyStreamGetBuffer());
   }
   if (dataBufferLength < dataSize)
   {
   dataStreamSetLength(dataSize);
   data = DbEntryOut(dataStreamGetBuffer());
   }
   continue;
   case ReadStatusSuccess:
   dataStreamPosition = ;
   dataStreamSetLength(dataSize);
   cust = (IPut)formatterDeserialize(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 stringFormat(ID:{} Key:{} ID Name);
   }
  
   public string Key
   {
   get { return Name; }
   }
   }
  操作
   using (BDBManager manager = new BDBManager(db dbdat))
   {
   bool success = managerSet(new Item() { ID = Name = TestText = });
   ConsoleWriteLine(stringFormat(set is {} success));
   }
  
   using (BDBManager manager = new BDBManager(db dbdat))
   {
   IPut put = new Item() { Name = Test };
   bool success = managerGet(ref put);
   ConsoleWriteLine(stringFormat(read is {}item : {} success putToString()));
   }
  
   using (BDBManager manager = new BDBManager(db dbdat))
   {
   IPut put = new Item() { Name = Test };
   bool success = managerRemove(put);
   ConsoleWriteLine(stringFormat(remove is {}item : {} success putToString()));
   }
  
   using (BDBManager manager = new BDBManager(db dbdat))
   {
   List<IPut> list = managerFind();
   foreach (var item in list)
   {
   ConsoleWriteLine(itemToString());
   }
   }
   ConsoleWriteLine(end);
   ConsoleReadKey();
From:http://tw.wingwit.com/Article/program/net/201311/12343.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.