嵌入式数据库包含很多,比如常用的sqlite、Access,此类文件类数据库不支持并发,是限制了桌面端系统的瓶颈。
sqlite并发可使用内存模式,弊端是系统异常或者电脑断电是造成数据丢失。
可尝试使用BerkeleyDB 或者FireBird 内嵌是数据库来满足需求。
本篇讲述BerkeleyDB 数据库
BerkeleyDB 是一种嵌入式的Key/Value的数据库,具有高速稳定的特性。
使用方法:
API地址:https://docs.oracle.com/database/bdb181/html/csharp/Index.html
附件demo(包含debug dll)基于Farmwork4.52
- 设置环境路径
- 打开数据库
- CURD(事务、单条)
- 判断是否存在
- 备份数据库
- 展示所有数据
- 关闭数据库
1.设置环境路径 根据不通的打包模式调用不同的分支
/// <summary>
/// 设置环境路径
/// </summary>
private void SetPath()
{
try
{
string pwd = Environment.CurrentDirectory;
pwd = Path.Combine(pwd, "..");
pwd = Path.Combine(pwd, "..");
if (IntPtr.Size == 4)
pwd = Path.Combine(pwd, "Win32");
else
pwd = Path.Combine(pwd, "x64");
#if DEBUG
pwd = Path.Combine(pwd, "Debug");
#else
pwd = Path.Combine(pwd, "Release");
#endif
home = pwd;
pwd += ";" + Environment.GetEnvironmentVariable("PATH");
Environment.SetEnvironmentVariable("PATH", pwd);
}
catch (DatabaseException e)
{
throw e;
}
}
2.打开数据库
public void Open()
{
try
{
/* Set up the environment.*/
DatabaseEnvironmentConfig envCfg = new DatabaseEnvironmentConfig();
envCfg.Create = true;
envCfg.UseMPool = true;
envCfg.UseLocking = true;
envCfg.UseLogging = true;
envCfg.UseTxns = true;
// Allow multiple threads visit to the environment handle.
envCfg.FreeThreaded = true;
if (inMem)
envCfg.Private = true;
else
envCfg.RunRecovery = true;
// Indicate that we want db to internally perform deadlock detection, aborting the transaction that has performed the least amount of WriteData activity in the event of a deadlock.
envCfg.LockSystemCfg = new LockingConfig();
envCfg.LockSystemCfg.DeadlockResolution = DeadlockPolicy.MIN_WRITE;
if (inMem)
{
// Specify in-memory logging.
envCfg.LogSystemCfg = new LogConfig();
envCfg.LogSystemCfg.InMemory = true;
// Specify the size of the in-memory log buffer Must be large enough to handle the log data created by the largest transaction.
envCfg.LogSystemCfg.BufferSize = 10 * 1024 * 1024;
// Specify the size of the in-memory cache, large enough to avoid paging to disk.
envCfg.MPoolSystemCfg = new MPoolConfig();
envCfg.MPoolSystemCfg.CacheSize = new CacheInfo(0, 10 * 1024 * 1024, 1);
}
/* Set up the database. */
BTreeDatabaseConfig dbCfg = new BTreeDatabaseConfig();
dbCfg.AutoCommit = true;
dbCfg.Creation = CreatePolicy.IF_NEEDED;
dbCfg.Duplicates = DuplicatesPolicy.NONE;
dbCfg.FreeThreaded = true;
dbCfg.ReadUncommitted = true;
// Open the environment. Any errors will be caught by the caller.
env = DatabaseEnvironment.Open(@"E:\o", envCfg);
//Open the database. Do not provide a txn handle. This Open is autocommitted because BTreeDatabaseConfig.AutoCommit is true.
dbCfg.Env = env;
//Open the environment. Any errors will be caught
btreeDB = BTreeDatabase.Open(dbName, dbCfg);
}
catch (DatabaseException e) { throw e; }
}
3.新增 修改
/// <summary>
/// 序列化型
/// </summary>
/// <param name="skey"></param>
/// <param name="sdata"></param>
public void SetObject(string skey, object sdata)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
new BinaryFormatter().Serialize(ms, sdata);
Byte[] bytes = ms.GetBuffer();
DatabaseEntry key = new DatabaseEntry(Encoding.Default.GetBytes(skey));
DatabaseEntry value = new DatabaseEntry(bytes);
btreeDB.Put(key, value);
}
}
catch (DatabaseException e)
{
throw e;
}
}
4.查询
/// <summary>
/// 获取指定键的值 序列化型
/// </summary>
/// <param name="skey"></param>
/// <returns></returns>
public object GetObject(string skey)
{
try
{
DatabaseEntry key = new DatabaseEntry(Encoding.Default.GetBytes(skey));
if (btreeDB.Exists(key))
{
KeyValuePair<DatabaseEntry, DatabaseEntry> pair = btreeDB.Get(key);
using (MemoryStream ms = new MemoryStream(pair.Value.Data))
{
return new BinaryFormatter().Deserialize(ms);
}
}
else
{
return null;
}
}
catch (DatabaseException e)
{
throw e;
}
}
5.删除
/// <summary>
/// 删除指定键
/// </summary>
/// <param name="skey"></param>
public void Delete(string skey)
{
try
{
DatabaseEntry key = new DatabaseEntry(Encoding.Default.GetBytes(skey));
if (btreeDB.Exists(key))
{
btreeDB.Delete(key);
}
}
catch (DatabaseException e)
{
throw e;
}
}
6.判断Key是否存在
/// <summary>
/// 判断是否存在
/// </summary>
/// <param name="skey"></param>
/// <returns></returns>
public bool Exists(string skey)
{
try
{
DatabaseEntry key = new DatabaseEntry(Encoding.Default.GetBytes(skey));
return btreeDB.Exists(key);
}
catch (DatabaseException e)
{
throw e;
}
}
7.备份数据库
/// <summary>
/// 备份数据库
/// </summary>
/// <param name="database"></param>
public void BackupDatabase(string database)
{
try
{
string target = Path.GetDirectoryName(database) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(database) + "_Back";
if (Directory.Exists(target))
Directory.Delete(target, true);
Directory.CreateDirectory(target);
BackupOptions opt = new BackupOptions();
opt.Creation = CreatePolicy.ALWAYS;
env.Backup(target, opt);
}
catch (DatabaseException e)
{
throw e;
}
}
8.展示所有数据
/// <summary>
/// 展示所有数据
/// </summary>
public void ShowALL()
{
try
{
using (Cursor dbc = btreeDB.Cursor())
{
foreach (KeyValuePair<DatabaseEntry, DatabaseEntry> p in dbc)
{
try
{
using (MemoryStream ms = new MemoryStream(p.Value.Data))//读取object
{
Console.WriteLine("{0}::{1}", Encoding.Default.GetString(p.Key.Data), new BinaryFormatter().Deserialize(ms));
}
}
catch (Exception ex)
{
//读取普通
Console.WriteLine("{0}::{1}", Encoding.Default.GetString(p.Key.Data), Encoding.Default.GetString(p.Value.Data));
}
}
}
}
catch (DatabaseException e)
{
throw e;
}
}