Skip to main content
 首页 » 编程设计

目前来说比较.net下最好的bdb操作封装(附单元测试)

2022年07月19日24exmyth
  1 using  System;
  2 using  System.Collections.Generic;
  3 using  System.IO;
  4 using  System.Linq;
  5 using  System.Runtime.Serialization.Formatters.Binary;
  6 using  System.Text;
  7 using  BerkeleyDb;
  8 using  Component;
  9
 10 namespace  ToolManager
 11 {
 12    public class BDBRecord
 13    {
 14        public object Key getset; }
 15        public string Value getset; }
 16    }
    /// <summary>
 17    /// BDB数据库操作类库
 18    /// </summary>

 19    public class BDBHelper
 20    {
 21
 22        private string DBFilePath getset; }
 23        private DBStoreType DBType getset; }
 24        public enum DBStoreType : byte
 25        {
 26            Auto=1,
 27            Queue,
 28            Hash
 29        }

 30        [Obsolete("该构造函数已废弃 ,请使用BDBHelper(string dbfilePath)")]
 31        public BDBHelper()
 32        {
 33        }

 34
 35        public BDBHelper(string dbfilePath)
 36        {
 37            this.DBFilePath = dbfilePath;
 38        }

 39        [Obsolete("该构造函数已废弃 ,请使用BDBHelper(string dbfilePath)")]
 40        public BDBHelper(string dbfilePath, DBStoreType type)
 41        {
 42            this.DBFilePath = dbfilePath;
 43            this.DBType = type;
 44        }

 45        public BDBRecord FindOne()
 46        {
 47            return this.FindOne(null);
 48        }

 49        public BDBRecord FindOne(Func<objectstringbool> predicate)
 50        {
 51            //Dictionary<string, object> dict = new Dictionary<string, object>();
 52            try
 53            {
 54                Queue格式
 85            }

 86            catch (Exception ex)
 87            {
 88                Hash格式
121                //}
122            }

123            //return dict;
124            return null;
125        }

126        public Dictionary<objectstring> FindAll(Func<objectstringbool> predicate)
127        {
128
129            Dictionary<objectstring> dict = new Dictionary<objectstring>();
130            try
131            {
132                Queue格式
150            }

151            catch (Exception ex)
152            {
153                Hash格式
173                //}
174            }

175            return dict;
176        }

177        public Dictionary<objectstring> FindAll()
178        {
179            //either below works fine
180            //return this.FindAll((s, o) => true);
181            return this.FindAll(null);
182        }

183        private static void _Do(KeyDataPair kvp, Func<objectstringbool> predicate, Dictionary<objectstring> result)
184        {
185            BinaryFormatter bf = new BinaryFormatter();
186            MemoryStream stream = new MemoryStream();
187            stream.Write(kvp.Data.Buffer, 0, kvp.Data.Size);
188            stream.Seek(0, SeekOrigin.Begin);
189            string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0, kvp.Key.Size);
190            object v = bf.Deserialize(stream);
191            if (predicate == null)
192            {
193                result.Add(v, k);
194            }

195            else if (predicate(v, k))
196            {
197                result.Add(v, k);
198            }

199        }

200        private static void _Do2(KeyDataPair kvp, Func<objectstringbool> predicate, Dictionary<objectstring> result)
201        {
202            BinaryFormatter bf = new BinaryFormatter();
203            MemoryStream stream = new MemoryStream();
204            stream.Write(kvp.Data.Buffer, 0, kvp.Data.Size);
205            stream.Seek(0, SeekOrigin.Begin);
206            string k = BitConverter.ToInt32(kvp.Key.Buffer, 0).ToString();
207            object v = bf.Deserialize(stream);
208            if (predicate == null)
209            {
210                result.Add(v, k);
211            }

212            else if (predicate(v, k))
213            {
214                result.Add(v, k);
215            }

216        }

217        /// <summary>
218        /// 更新数据库中的数据
219        /// </summary>
220        /// <param name="predicate">execute condition</param>
221        /// <param name="isMatchOnlyOnce">is match only once</param>
222        /// <returns>effect records</returns>

223        public int UpdateInQueueMode(Func<intobjectbool> predicate, object value,bool isMatchOnlyOnce)
224        {
225                 int count = 0;
226                 if (predicate == null)
227                     return 0;
228               //遍历数据
229                using (Db db = new Db(DbCreateFlags.None))
230                {
231                    db.RecLen = 5000;
232                    db.RecPad = '.';
233                    //这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
234                    //Db.OpenFlags.Truncate会清空数据库
235                    DbQueue dbf = (DbQueue)db.Open(nullthis.DBFilePath, null, DbType.Queue,
236        Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create, 0);
237
238                    using (DbQueueCursor cursor = dbf.OpenCursor(null, DbFileCursor.CreateFlags.None))
239                    {
240                        BinaryFormatter bf = new BinaryFormatter();
241                        MemoryStream stream = new MemoryStream();
242                        foreach (KeyDataPair kdp in cursor)
243                        {
244                            int k = BitConverter.ToInt32(kdp.Key.Buffer, 0);
245                            Console.WriteLine("k={0}", k.ToString());
246                            stream.SetLength(0);
247                            stream.Position = 0;
248                            stream.Write(kdp.Data.Buffer, 0, kdp.Data.Size);
249                            stream.Seek(0, SeekOrigin.Begin);
250                            object v = bf.Deserialize(stream);
251                            if(predicate(k,v))
252                            {
253                                count++;
254                                //string d = Encoding.UTF8.GetString(kdp.Data.Buffer, 0, kdp.Data.Size);
255                                //如何读取Queue类型的主键值
256
257
258                                //Console.WriteLine("{0},{1}", p2.State, p2.Os);
259                                //p2.Os = "changed";
260                                //stream = new MemoryStream();
261                                stream.Position = 0;
262                                stream.SetLength(0);
263                                bf.Serialize(stream, value);
264                                DbEntry data = DbEntry.InOut(stream.ToArray());
265                                cursor.Put(ref data);
266                                if (isMatchOnlyOnce)
267                                {
268                                    stream.Close();
269                                    return count;
270                                }

271                            }

272                        }

273                            stream.Close();
274                    }

275            }

276            return count;
277        }

278
279        public void CreateInQueueMode(object value)
280        {
281            Db PC = new Db(DbCreateFlags.None);
282            PC.RecLen = 5000;
283            PC.RecPad = '.';
284            DbQueue file = (DbQueue)PC.Open(nullthis.DBFilePath, null, DbType.Queue, Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe, 0);
285            //CreateSecondaryDB(file,"Id.PCs.s",new DbFile.KeyGeneratorFcn(Common.Id));
286            //CreateSecondaryDB(file, "Id.PCs.s", new DbFile.KeyGeneratorFcn(Common.Id));
287            //由于数据量不是很大,不考虑使用二级数据库,直接使用游标操作,降低复杂度
288            //首先遍历数据库看有没有已经存在,如果没有,则添加一个,如果有,改变其状态
289            BinaryFormatter bf = new BinaryFormatter();
290            MemoryStream stream= new MemoryStream();
291            bf.Serialize(stream, value);
292            DbEntry k = DbEntry.Out(new byte[1024]);
293            DbEntry data = DbEntry.InOut(stream.ToArray());
294            file.Append(nullref k, ref data);
295            stream.Close();
296            file.Sync();
297            PC.Close();
298        }

299        public int DeleteInQueueMode(Func<intobjectbool> predicate,bool isMatchOnlyOnce)
300        {
301            int count = 0;
302            if (predicate == null)
303                return 0;
304            //遍历数据
305            using (Db db = new Db(DbCreateFlags.None))
306            {
307                db.RecLen = 5000;
308                db.RecPad = '.';
309                //这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
310                //Db.OpenFlags.Truncate会清空数据库
311                DbQueue dbf = (DbQueue)db.Open(nullthis.DBFilePath, null, DbType.Queue,
312    Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create, 0);
313
314                using (DbQueueCursor cursor = dbf.OpenCursor(null, DbFileCursor.CreateFlags.None))
315                {
316                    BinaryFormatter bf = new BinaryFormatter();
317                    MemoryStream stream = new MemoryStream();
318                    foreach (KeyDataPair kdp in cursor)
319                    {
320                        int k = BitConverter.ToInt32(kdp.Key.Buffer, 0);
321                        Console.WriteLine("k={0}", k.ToString());
322                        stream.SetLength(0);
323                        stream.Position = 0;
324                        stream.Write(kdp.Data.Buffer, 0, kdp.Data.Size);
325                        stream.Seek(0, SeekOrigin.Begin);
326                        object v = bf.Deserialize(stream);
327                        if (predicate(k, v))
328                        {
329                            count++;
330                            //string d = Encoding.UTF8.GetString(kdp.Data.Buffer, 0, kdp.Data.Size);
331                            //如何读取Queue类型的主键值
332
333
334                            //Console.WriteLine("{0},{1}", p2.State, p2.Os);
335                            //p2.Os = "changed";
336                            //stream = new MemoryStream();
337                            //stream.Position = 0;
338                            //stream.SetLength(0);
339                            //bf.Serialize(stream, v);
340                            //DbEntry data = DbEntry.InOut(stream.ToArray());
341                            //cursor.Put(ref data);
342                            cursor.Delete();
343                            if (isMatchOnlyOnce)
344                            {
345                                stream.Close();
346                                return count;
347                            }

348                        }

349                    }
stream.Close();
350                }

351            }

352            return count;
353        }

354
355        /// <summary>
356        /// 用于向支持重复键值的数据库文件添加数据
357        /// </summary>
358        /// <param name="key"></param>
359        /// <param name="value"></param>

360        public void CreateInHashModeWithDup(string key,object value)
361        {
362            //这里只是更新了一条记录,更新多条同key的情况没有考虑
363            Db db = new Db(DbCreateFlags.None);
364            db.SetFlags(DbFlags.Dup);
365            DbFile dbf = db.Open(nullthis.DBFilePath, null, DbType.Hash, Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe, 0);
366            MemoryStream stream = new MemoryStream();
367            BinaryFormatter formatter = new BinaryFormatter();
368            formatter.Serialize(stream, value);
369            DbEntry _key = DbEntry.InOut(Encoding.UTF8.GetBytes(key));
370            DbEntry _data = DbEntry.InOut(stream.ToArray());
371            if (dbf.Put(nullref _key, ref _data) != 0)
372                Console.Write("{0}:输入错误", key);
373            stream.Close();
374            dbf.Sync();//数据更新 
375            db.Close();
376        }

377        /// <summary>
378        /// 默认方式,如果已有键则进行更新操作
379        /// </summary>
380        /// <param name="key"></param>
381        /// <param name="value"></param>

382        public void CreateOrUpdateInHashModeWithoutDup(string key,object value)
383        {
384            //这里只是更新了一条记录,更新多条同key的情况没有考虑
385            Db db = new Db(DbCreateFlags.None);
386            //db.SetFlags(DbFlags.Dup);
387            DbFile dbf = db.Open(nullthis.DBFilePath, null, DbType.Hash, Db.OpenFlags.Create|Db.OpenFlags.ThreadSafe, 0);
388            MemoryStream stream = new MemoryStream();
389            BinaryFormatter formatter = new BinaryFormatter();
390            formatter.Serialize(stream, value);
391            DbEntry _key = DbEntry.InOut(Encoding.UTF8.GetBytes(key));
392            DbEntry _data = DbEntry.InOut(stream.ToArray());
393            if (dbf.Put(nullref _key, ref _data) != 0)
394                Console.Write("{0}:输入错误", key);
395            stream.Close();
396            dbf.Sync();//数据更新 
397            db.Close();
398        }

399        public int UpdateInHashMode(Func<string,object,bool> predicate,object value,bool isMatchOnlyOnce)
400        {
401            int count = 0;
402            if (predicate == null)
403                return count;
404           //遍历数据
405            using (Db db = new Db(DbCreateFlags.None))
406            {
407                //这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
408                //Db.OpenFlags.Truncate会清空数据库
409                DbHash dbf = (DbHash)db.Open(nullthis.DBFilePath, null, DbType.Hash,
410    Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create, 0);
411
412                using (DbHashCursor cursor = dbf.OpenCursor(null, DbFileCursor.CreateFlags.None))
413                {
414                    BinaryFormatter bf = new BinaryFormatter();
415                    MemoryStream stream = new MemoryStream();
416                   foreach (KeyDataPair kvp in cursor)
417                    {
418                        stream.SetLength(0);
419                        stream.Position = 0
420                        stream.Write(kvp.Data.Buffer, 0, kvp.Data.Size);
421                        stream.Seek(0, SeekOrigin.Begin);
422                        string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0, kvp.Key.Size);
423                        object v = bf.Deserialize(stream);
424                        if (predicate(k, v))
425                        {
426                            count++;
427                            stream.SetLength(0);
428                            stream.Position = 0;
429                            bf.Serialize(stream, value);
430                            DbEntry data = DbEntry.InOut(stream.ToArray());
431                            cursor.Put(ref data, DbKeyCursor<DbHashCursor, DbHash>.PutMode.Current);
432                            if (isMatchOnlyOnce)
433                            {
434                                stream.Close();
435                                return count;
436                            }

437                        }

438                    }

439                    stream.Close();
440                }

441            }

442            return count;
443        }

444        public int DeleteInHashMode(Func<string,object,bool> predicate,bool isMatchOnlyOnce)
445        {
446            int count = 0;
447            if (predicate == null)
448                return count;
449            //遍历数据
450            using (Db db = new Db(DbCreateFlags.None))
451            {
452                //这里如果应用Db.OpenFlags.Create则在启动后会覆盖同名文件,并新建同名文件
453                //Db.OpenFlags.Truncate会清空数据库
454                DbHash dbf = (DbHash)db.Open(nullthis.DBFilePath, null, DbType.Hash,
455    Db.OpenFlags.ThreadSafe|Db.OpenFlags.Create, 0);
456
457                using (DbHashCursor cursor = dbf.OpenCursor(null, DbFileCursor.CreateFlags.None))
458                {
459                    BinaryFormatter bf = new BinaryFormatter();
460                    MemoryStream stream = new MemoryStream();
461                    foreach (KeyDataPair kvp in cursor)
462                    {
463                        stream.SetLength(0);
464                        stream.Position = 0;
465                        stream.Write(kvp.Data.Buffer, 0, kvp.Data.Size);
466                        stream.Seek(0, SeekOrigin.Begin);
467                        string k = Encoding.UTF8.GetString(kvp.Key.Buffer, 0, kvp.Key.Size);
468                        object v = bf.Deserialize(stream);
469                        if (predicate(k, v))
470                        {
471                            count++;
472                            cursor.Delete();
473                            if (isMatchOnlyOnce)
474                            {
475                                stream.Close();
476                                return count;
477                            }

478                        }

479                    }

480                    stream.Close();
481                }

482            }

483            return count;
484        }

485    }

486}

487

unit test code

  1 using  System;
  2 using  System.Collections.Generic;
  3 using  System.Linq;
  4 using  System.Text;
  5 using  Component;
  6 using  MbUnit.Framework;
  7
  8 namespace  ToolManager.Test
  9 {
 10    [TestFixture]
 11    class BDBHelperTest2
 12    {
 13        hash mode unit test
 69
 70        queue mode unit test
103
104    }

105}

106

本文参考链接:https://www.cnblogs.com/lexus/archive/2008/08/24/1275164.html