.net下BerkeleyDB操作封装C#版(附单元测试)
using System;
using System.Collections.Generic;
using
System.IO;
using System.Linq;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Text;
using BerkeleyDb;
using Component;
namespace
ToolManager
{
public class BDBRecord
{
public object Key { get; set;
}
public string Value { get; set;
}
} /**//// <summary>
/// BDB数据库操作类库
/// </summary>
public class
BDBHelper
{
private
string DBFilePath { get; set; }
private
DBStoreType DBType { get; set; }
public
enum DBStoreType : byte
{
Auto=1,
Queue,
Hash
}
[Obsolete("该构造函数已废弃
,请使用BDBHelper(string dbfilePath)")]
public BDBHelper()
{
}
public BDBHelper(string
dbfilePath)
{
this.DBFilePath = dbfilePath;
}
[Obsolete("该构造函数已废弃
,请使用BDBHelper(string dbfilePath)")]
public BDBHelper(string dbfilePath, DBStoreType
type)
{
this.DBFilePath =
dbfilePath;
this.DBType = type;
}
public BDBRecord
FindOne()
{
return
this.FindOne(null);
}
public BDBRecord
FindOne(Func<object, string, bool>
predicate)
{
//Dictionary<string, object> dict = new Dictionary<string,
object>();
try
{
Queue格式#region
Queue格式
//if (this.DBType ==
DBStoreType.Queue)
//{
using (Db db = new
Db(DbCreateFlags.None))
{
db.RecLen =
5000;
db.RecPad =
‘.‘;
DbQueue file = (DbQueue)db.Open(null, this.DBFilePath, null, DbType.Queue,
Db.OpenFlags.Create,
0);
using (DbQueueCursor cursor = file.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
foreach (KeyDataPair kvp in
cursor)
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = BitConverter.ToInt32(kvp.Key.Buffer,
0).ToString();
object v =
bf.Deserialize(stream);
if (predicate ==
null)
{
return new BDBRecord() { Key = v, Value = k
};
}
else if (predicate(v,
k))
{
return new BDBRecord() { Key = v, Value = k
};
}
}
}
}
//}
#endregion
}
catch
(Exception ex)
{
Hash格式#region
Hash格式
//else
if(this.DBType==DBStoreType.Hash)
//{
//遍历数据
using (Db db = new
Db(DbCreateFlags.None))
{
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbHash dbf = (DbHash)db.Open(null, this.DBFilePath, null,
DbType.Hash,
Db.OpenFlags.ThreadSafe,
0);
using (DbHashCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
foreach (KeyDataPair kvp in
cursor)
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0,
kvp.Key.Size);
object v =
bf.Deserialize(stream);
if (predicate ==
null)
{
return new BDBRecord() { Key = v, Value = k
};
}
else if (predicate(v,
k))
{
return new BDBRecord() { Key = v, Value = k
};
}
}
}
}
#endregion
//}
}
//return
dict;
return
null;
}
public Dictionary<object,
string> FindAll(Func<object, string, bool>
predicate)
{
Dictionary<object, string> dict = new Dictionary<object,
string>();
try
{
Queue格式#region
Queue格式
//if (this.DBType ==
DBStoreType.Queue)
//{
using (Db db = new
Db(DbCreateFlags.None))
{
db.RecLen =
5000;
db.RecPad =
‘.‘;
DbQueue file = (DbQueue)db.Open(null, this.DBFilePath, null, DbType.Queue,
Db.OpenFlags.Create,
0);
using (DbQueueCursor cursor = file.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
foreach (KeyDataPair kvp in
cursor)
{
_Do2(kvp, predicate,
dict);
}
}
}
//}
#endregion
}
catch
(Exception ex)
{
Hash格式#region
Hash格式
//else
if(this.DBType==DBStoreType.Hash)
//{
//遍历数据
using (Db db = new
Db(DbCreateFlags.None))
{
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbHash dbf = (DbHash)db.Open(null, this.DBFilePath, null,
DbType.Hash,
Db.OpenFlags.ThreadSafe,
0);
using (DbHashCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
foreach (KeyDataPair kdp in
cursor)
{
_Do(kdp, predicate,
dict);
}
}
}
#endregion
//}
}
return
dict;
}
public Dictionary<object,
string> FindAll()
{
//either below
works fine
//return this.FindAll((s, o) =>
true);
return
this.FindAll(null);
}
private static void _Do(KeyDataPair
kvp, Func<object, string, bool> predicate, Dictionary<object,
string> result)
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0,
kvp.Key.Size);
object v =
bf.Deserialize(stream);
if (predicate ==
null)
{
result.Add(v,
k);
}
else if
(predicate(v,
k))
{
result.Add(v,
k);
}
}
private static void _Do2(KeyDataPair
kvp, Func<object, string, bool> predicate, Dictionary<object,
string> result)
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = BitConverter.ToInt32(kvp.Key.Buffer,
0).ToString();
object v =
bf.Deserialize(stream);
if (predicate ==
null)
{
result.Add(v,
k);
}
else if
(predicate(v,
k))
{
result.Add(v,
k);
}
}
/**////
<summary>
///
更新数据库中的数据
///
</summary>
/// <param
name="predicate">execute
condition</param>
/// <param
name="isMatchOnlyOnce">is match only
once</param>
///
<returns>effect
records</returns>
public int
UpdateInQueueMode(Func<int, object, bool> predicate, object value,bool
isMatchOnlyOnce)
{
int count =
0;
if (predicate ==
null)
return
0;
//遍历数据
using (Db db = new
Db(DbCreateFlags.None))
{
db.RecLen =
5000;
db.RecPad =
‘.‘;
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbQueue dbf = (DbQueue)db.Open(null, this.DBFilePath, null,
DbType.Queue,
Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create,
0);
using (DbQueueCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
foreach (KeyDataPair kdp in
cursor)
{
int k = BitConverter.ToInt32(kdp.Key.Buffer,
0);
Console.WriteLine("k={0}",
k.ToString());
stream.SetLength(0);
stream.Position =
0;
stream.Write(kdp.Data.Buffer, 0,
kdp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
object v =
bf.Deserialize(stream);
if(predicate(k,v))
{
count++;
//string d = Encoding.UTF8.GetString(kdp.Data.Buffer, 0,
kdp.Data.Size);
//如何读取Queue类型的主键值
//Console.WriteLine("{0},{1}", p2.State,
p2.Os);
//p2.Os =
"changed";
//stream = new
MemoryStream();
stream.Position =
0;
stream.SetLength(0);
bf.Serialize(stream,
value);
DbEntry data =
DbEntry.InOut(stream.ToArray());
cursor.Put(ref
data);
if
(isMatchOnlyOnce)
{
stream.Close();
return
count;
}
}
}
stream.Close();
}
}
return
count;
}
public void
CreateInQueueMode(object value)
{
Db PC = new
Db(DbCreateFlags.None);
PC.RecLen =
5000;
PC.RecPad
= ‘.‘;
DbQueue
file = (DbQueue)PC.Open(null, this.DBFilePath, null, DbType.Queue,
Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe,
0);
//CreateSecondaryDB(file,"Id.PCs.s",new
DbFile.KeyGeneratorFcn(Common.Id));
//CreateSecondaryDB(file, "Id.PCs.s", new
DbFile.KeyGeneratorFcn(Common.Id));
//由于数据量不是很大,不考虑使用二级数据库,直接使用游标操作,降低复杂度
//首先遍历数据库看有没有已经存在,如果没有,则添加一个,如果有,改变其状态
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream= new
MemoryStream();
bf.Serialize(stream,
value);
DbEntry
k = DbEntry.Out(new
byte[1024]);
DbEntry data =
DbEntry.InOut(stream.ToArray());
file.Append(null, ref k, ref
data);
stream.Close();
file.Sync();
PC.Close();
}
public int
DeleteInQueueMode(Func<int, object, bool> predicate,bool
isMatchOnlyOnce)
{
int count =
0;
if (predicate
==
null)
return 0;
//遍历数据
using (Db
db = new
Db(DbCreateFlags.None))
{
db.RecLen =
5000;
db.RecPad =
‘.‘;
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbQueue dbf = (DbQueue)db.Open(null, this.DBFilePath, null,
DbType.Queue,
Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create,
0);
using (DbQueueCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
foreach (KeyDataPair kdp in
cursor)
{
int k = BitConverter.ToInt32(kdp.Key.Buffer,
0);
Console.WriteLine("k={0}",
k.ToString());
stream.SetLength(0);
stream.Position =
0;
stream.Write(kdp.Data.Buffer, 0,
kdp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
object v =
bf.Deserialize(stream);
if (predicate(k,
v))
{
count++;
//string d = Encoding.UTF8.GetString(kdp.Data.Buffer, 0,
kdp.Data.Size);
//如何读取Queue类型的主键值
//Console.WriteLine("{0},{1}", p2.State,
p2.Os);
//p2.Os =
"changed";
//stream = new
MemoryStream();
//stream.Position =
0;
//stream.SetLength(0);
//bf.Serialize(stream,
v);
//DbEntry data =
DbEntry.InOut(stream.ToArray());
//cursor.Put(ref
data);
cursor.Delete();
if
(isMatchOnlyOnce)
{
stream.Close();
return
count;
}
}
}stream.Close();
}
}
return
count;
}
/**////
<summary>
///
用于向支持重复键值的数据库文件添加数据
///
</summary>
/// <param
name="key"></param>
///
<param name="value"></param>
public void CreateInHashModeWithDup(string key,object
value)
{
//这里只是更新了一条记录,更新多条同key的情况没有考虑
Db db = new
Db(DbCreateFlags.None);
db.SetFlags(DbFlags.Dup);
DbFile dbf = db.Open(null, this.DBFilePath, null, DbType.Hash,
Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe,
0);
MemoryStream
stream = new
MemoryStream();
BinaryFormatter formatter = new
BinaryFormatter();
formatter.Serialize(stream,
value);
DbEntry
_key =
DbEntry.InOut(Encoding.UTF8.GetBytes(key));
DbEntry _data =
DbEntry.InOut(stream.ToArray());
if (dbf.Put(null, ref _key, ref _data) !=
0)
Console.Write("{0}:输入错误",
key);
stream.Close();
dbf.Sync();//数据更新
db.Close();
}
/**////
<summary>
///
默认方式,如果已有键则进行更新操作
///
</summary>
/// <param
name="key"></param>
///
<param name="value"></param>
public void CreateOrUpdateInHashModeWithoutDup(string key,object
value)
{
//这里只是更新了一条记录,更新多条同key的情况没有考虑
Db db = new
Db(DbCreateFlags.None);
//db.SetFlags(DbFlags.Dup);
DbFile dbf = db.Open(null, this.DBFilePath, null, DbType.Hash,
Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe,
0);
MemoryStream
stream = new
MemoryStream();
BinaryFormatter formatter = new
BinaryFormatter();
formatter.Serialize(stream,
value);
DbEntry
_key =
DbEntry.InOut(Encoding.UTF8.GetBytes(key));
DbEntry _data =
DbEntry.InOut(stream.ToArray());
if (dbf.Put(null, ref _key, ref _data) !=
0)
Console.Write("{0}:输入错误",
key);
stream.Close();
dbf.Sync();//数据更新
db.Close();
}
public int
UpdateInHashMode(Func<string,object,bool> predicate,object value,bool
isMatchOnlyOnce)
{
int count =
0;
if (predicate
==
null)
return count;
//遍历数据
using (Db
db = new
Db(DbCreateFlags.None))
{
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbHash dbf = (DbHash)db.Open(null, this.DBFilePath, null,
DbType.Hash,
Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create,
0);
using (DbHashCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
foreach (KeyDataPair kvp in
cursor)
{
stream.SetLength(0);
stream.Position = 0;
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0,
kvp.Key.Size);
object v =
bf.Deserialize(stream);
if (predicate(k,
v))
{
count++;
stream.SetLength(0);
stream.Position =
0;
bf.Serialize(stream,
value);
DbEntry data =
DbEntry.InOut(stream.ToArray());
cursor.Put(ref data, DbKeyCursor<DbHashCursor,
DbHash>.PutMode.Current);
if
(isMatchOnlyOnce)
{
stream.Close();
return
count;
}
}
}
stream.Close();
}
}
return
count;
}
public int
DeleteInHashMode(Func<string,object,bool> predicate,bool
isMatchOnlyOnce)
{
int count =
0;
if (predicate
==
null)
return count;
//遍历数据
using (Db
db = new
Db(DbCreateFlags.None))
{
//这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
//Db.OpenFlags.Truncate会清空数据库
DbHash dbf = (DbHash)db.Open(null, this.DBFilePath, null,
DbType.Hash,
Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create,
0);
using (DbHashCursor cursor = dbf.OpenCursor(null,
DbFileCursor.CreateFlags.None))
{
BinaryFormatter bf = new
BinaryFormatter();
MemoryStream stream = new
MemoryStream();
foreach (KeyDataPair kvp in
cursor)
{
stream.SetLength(0);
stream.Position =
0;
stream.Write(kvp.Data.Buffer, 0,
kvp.Data.Size);
stream.Seek(0,
SeekOrigin.Begin);
string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0,
kvp.Key.Size);
object v =
bf.Deserialize(stream);
if (predicate(k,
v))
{
count++;
cursor.Delete();
if
(isMatchOnlyOnce)
{
stream.Close();
return
count;
}
}
}
stream.Close();
}
}
return
count;
}
}
}