Db4o for .NET 使用心得(1、2):Trace db4o;慎用struct

Db4o(http://www.db4o.com/)是著名的开源对象数据库,使用它能够将持续层代码量降低到忽略不计的程度。如果数据量不大,用它能够将开发速度提高一个层次。
我手中的小项目需要储存约十万个联系人的数据,考察了sqlite与db4o,最终决定选用db4o. 我使用的是db4o 7.4 for .NET 2.0。关于db4o网上有很多文档,然而有一些问题,在网上不容易找到解决办法,总结一下,写在下面。

(1) Trace db4o

ObjectManager是官方查看db4o数据库的客户端,然而,db4o7.4这个版本对应的ObjectManager不再免费,用不了了。要弄清楚在程序中db4o数据库到底做了哪些事情,除了ObjectManager外,还可以打开db4o 的日志,进行跟踪。

在打开数据库之前,进行Trace操作的代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code

#if DEBUG
   Db4objects.Db4o.Db4oFactory.Configure().MessageLevel(
3);
#endif
   IObjectContainer ObjectContainer 
= Db4oFactory.OpenFile("test.yap");

 

这样,在VS的output窗口或者控制台里会有相关的操作日志,如:

[db4o  7.4 . 60.11658     2008 - 10 - 16   07 : 59 : 06
 
17563  update Orc.ContactManager.Contact, 联系人管理器
[db4o 
7.4 . 60.11658     2008 - 10 - 16   07 : 59 : 06
 
346372   new  System.Guid, mscorlib
[db4o 
7.4 . 60.11658     2008 - 10 - 16   07 : 59 : 06
 
346415   new  Orc.ContactManager.ChannelType, 联系人管理器
[db4o 
7.4 . 60.11658     2008 - 10 - 16   07 : 59 : 06
 
17770  update Orc.ContactManager.Contact, 联系人管理器
[db4o 
7.4 . 60.11658     2008 - 10 - 16   07 : 59 : 06
 
346571   new  System.Guid, mscorlib

 

2 尽量少用struct, enum

目前db4o处理普通struct及enum还不尽如意。
对于普通的struct及enum,db4o不能辨别待储存/更新的实例与数据库中原有实例是否同一实例,因此当update时,即使值没有变动,db4o也会将它new一个出来,储存入数据库。如果仅仅只是这样,不过浪费了一些无谓的IO操作,更大的问题是它储存进去一个新值,却不删除原有的值,导致数据库文件中存在大量的垃圾数据。

通过下面小程序就可以验证这一缺陷:

ContractedBlock.gif ExpandedBlockStart.gif Code
 public class Contact
 {
  
public String Id { getset; }
  
public String Name { getset; }
  
public Contact(String id, String name)
  {
   Id 
= id;
   Name 
= name;
  }

  
public static Contact Random()
  {
   
return new Contact(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
  }
 }

 
public class Program
 {
  
static void Main(string[] args)
  {
#if DEBUG
   Db4objects.Db4o.Db4oFactory.Configure().MessageLevel(
3);
#endif
   IObjectContainer ObjectContainer 
= Db4oFactory.OpenFile("test.yap");
   Contact c 
= Contact.Random();
   
for (int i = 0; i < 1000; i++)
   {
    c.Name 
= i.ToString();
    ObjectContainer.Store(c);
   }
   ObjectContainer.Commit();
   ObjectContainer.Close();
   Console.WriteLine(
"OK!");
   Console.ReadLine();
  }
 }

 

程序运行结束后,数据库文件test.yap 大小为2k.

运行日志如下:


[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 42 : 39 ]
 
914  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 42 : 39 ]
 
914  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 42 : 39 ]
 
914  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 42 : 39 ]
 
914  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 42 : 39 ]
 
914  update Db4oTest.Contact, Db4oTest


可见,每次运行ObjectContainer.Store(c)均对c进行update。

将Contact的代码改为:

ContractedBlock.gif ExpandedBlockStart.gif Code
 public enum ContactType
 {
  Type1,
  Type2
 }

 
public class Contact
 {
  
public String Id { getset; }
  
public String Name { getset; }
  
public Guid Guid { getset; }
  
public Int32 Code { getset; }
  
public ContactType Type { getset; }
  
public Contact(String id, String name)
  {
   Id 
= id;
   Name 
= name;
   Guid 
= Guid.NewGuid();
   Code 
= Guid.GetHashCode();
   Type 
= ContactType.Type1;
  }

  
public static Contact Random()
  {
   
return new Contact(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
  }
 }

 

编译程序,删除test.yap文件,重新运行程序,得到新的test.yap文件大小为144k,可见其中存在大量的垃圾数据。查看日志信息可以发现问题所在:


2352  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 48 : 56 ]
 
99639   new  System.Guid, mscorlib
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 48 : 56 ]
 
99682   new  Db4oTest.ContactType, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 48 : 56 ]
 
2352  update Db4oTest.Contact, Db4oTest
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 48 : 56 ]
 
99716   new  System.Guid, mscorlib
[db4o 
7.4 . 60.11658     2008 - 10 - 16   09 : 48 : 56 ]
 
99759   new  Db4oTest.ContactType, Db4oTest

 

可见每update一次Contact c,db4o都要new一个Guid,new 一个ContactType,存入数据库,原有的Guid/ContactType,则变成垃圾,依旧呆在数据库中,导致数据库文件急剧增长。

.net下,Int32也是一种struct,然而,从上例日志中却未发现新建Int32 Code,我猜测是db4o对Int32这些常用struct进行了特殊处理。

为了避免垃圾数据,使用db4o时最好慎用struct。

转载于:https://www.cnblogs.com/xiaotie/archive/2008/10/16/1312397.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值