2009年6月28日 星期日

db4o 的 Activation

我們在之前的文章提過關於物件更新深度的問題。db4o 的 Activation 則是設計用來簡化處理更新深度問題,達到 transpartent activation 的效果!

如同在物件更新深度一文中提到的,我們先將資料庫內塞滿 Article 物件。若是我們不再開啟資料庫前設定好更新深度的相關參數,則可能會造成取出的物件有部分內容是 null 值。

要讓 db4o 運行於 Transparent Activation 模式的方法很簡單:

Db4oFactory.Configure().Add(new TransparentActivationSupport());
就這樣,我們不需要再擔心會遇到 null 值的問題了!實際上,當啟用 Transparent Activation 模式時,任何未實做 Db4objects.Db4o.TA.IActivatable 介面的物件被使用時將會自動的 activate。很明顯的是,這種方式會造成記憶體的大量消耗,也造成載入時間變慢。要避免這種情況,我們可以替我們的類別實做 Activatable 介面。下面是我們將 Article 物件加上 Activatable 的實做:
public class Article: IActivatable
{  
   // ...

   [Transient]
   private IActivator _activator;

   private Sentence title;  
   public Sentence SentenceOfTitle  
   {  
       get { Activate(ActivationPurpose.Read);
             return title; }  
       set { Activate(ActivationPurpose.Write);
             title = value; }  
   }  
   
   // 這裡假設 IsStructure 不需要 activation
   private bool _IsStructure;  
   public bool IsStructure  
   {  
       get { // Activate(ActivationPurpose.Read);
             return _IsStructure; }  
       set { // Activate(ActivationPurpose.Write);
             _IsStructure = value; }  
   }  
   
    private List _SentencesOfAbs;  
    public List SentencesOfAbstract  
    {  
       get { Activate(ActivationPurpose.Read);
             return _SentencesOfAbs; }  
       set { Activate(ActivationPurpose.Write);
             _SentencesOfAbs = value; }  
    }  

    public override String ToString()
    {
       Activate(ActivationPurpose.Read);
       return string.Format("T:{0}", title);
    }

    // implement IActivatable
    public void Activate(ActivationPurpose purpose)
    {
        if(_activator != null)
        {
            _activator.Activate(purpose);
        }
    }
    public void Bind(IActivator activator)
    {
        if (_activator == activator)
        {
            return;
        }
        if (activator != null && null != _activator)
        {
            throw new System.InvalidOperationException();
        }
        _activator = activator;
    }
} 
一個 IActivatable 類別必須儲存 db4o 提供給 bind 方法的Activator 物件於一個 transient 變數中(上例中的 _activator 變數),並且在預被 active 的欄位被呼叫前,呼叫 Activate() 方法。假若該物件已經被 activate,這個方法會立即回傳,否則 activation 會自動發生。

沒有留言: