VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • c#实现Berkeley操作简介

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

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

 六、完整操作封装

 

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

 

  另外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;
  }
  }



相关教程