<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns:MadCap="http://www.madcapsoftware.com/Schemas/MadCap.xsd" MadCap:lastBlockDepth="2" MadCap:lastHeight="120" MadCap:lastWidth="624" MadCap:disableMasterStylesheet="true" MadCap:tocPath="Basics Operations & Concepts|Activation|Transparent Activation" MadCap:InPreviewMode="false" MadCap:RuntimeFileType="Topic" MadCap:TargetType="WebHelp" MadCap:PathToHelpSystem="../../../../" MadCap:HelpSystemFileName="index.xml" MadCap:SearchType="Stem"> <head><title>Transparent Activation Example</title> <script type="text/javascript">/* <![CDATA[ */ window.onload = function(){ var pathToFlash = $('html').attr('MadCap:PathToHelpSystem') + 'Content/Resources/Code/ZeroClipboard.swf'; ZeroClipboard.setMoviePath(pathToFlash); function bindToClipBord(element,content){ var clip = new ZeroClipboard.Client(); clip.setText(content); clip.glue(element); }; if(location.protocol==='file:'){ $('.copylink-marker').remove(); } else{ $('.copylink-marker').each(function(){ var text = $(this).parent().parent().children('.prettyprint').html(); $(this).hover(function(){ bindToClipBord(this,text); }, function(){}); }); } prettyPrint(); }; /* ]]> */</script> <link href="../../../SkinSupport/MadCap.css" rel="stylesheet" /> <link href="../../../Resources/Stylesheets/OnlineStyle.css" rel="stylesheet" /> <script src="../../../SkinSupport/MadCapAll.js"> </script> <script src="../../../Resources/Code/prettify.js"> </script> <script src="../../../Resources/Code/lang-vb.js"> </script> <script src="../../../Resources/Code/jquery.min.js"> </script> <script src="../../../Resources/Code/ZeroClipboard.js"> </script> </head> <body> <p class="MCWebHelpFramesetLink" style="display: none;"><a href="../../../../index_CSH.html#basics/activation_concept/transparent_activation_framework/detailed_example.htm" style="">Open topic with navigation</a> </p> <div class="MCBreadcrumbsBox"><span class="MCBreadcrumbsPrefix">You are here: </span><a class="MCBreadcrumbsLink" href="../../../basics.htm">Basics Operations & Concepts</a><span class="MCBreadcrumbsDivider"> > </span><a class="MCBreadcrumbsLink" href="../../activation.htm">Activation</a><span class="MCBreadcrumbsDivider"> > </span><a class="MCBreadcrumbsLink" href="../transparent_activation_framework.htm">Transparent Activation</a><span class="MCBreadcrumbsDivider"> > </span><span class="MCBreadcrumbs">Example</span> </div> <p> <script type="text/javascript">/*<![CDATA[*/document.write('<a href="' + location.href +'">'); document.write("Direct Link"); document.write('</a>');/*]]>*/</script> </p> <p> </p> <h1>Transparent Activation Example</h1> <p>In order to support Transparent <span class="MCPopup"><a href="javascript:void(0);" class="MCPopupSpot" onclick="FMCPopup( event, this ); return false;" MadCap:src="../../activation.htm">Activation<img style="border: none;margin-left: 5px;" src="../../../SkinSupport/ExpandingClosed.gif" MadCap:altsrc="../../../SkinSupport/ExpandingOpen.gif" class="MCExpandingIcon" onload="if ( typeof( FMCPreloadImage ) == 'function' ) { FMCPreloadImage( '../../../SkinSupport/ExpandingOpen.gif' ); }" /></a></span>, the objects which are stored in the database need to implement the <span class="PrimaryActivatable">IActivatable</span>-interface.</p> <p>An object which implements the <span class="PrimaryActivatable">IActivatable</span>-interface is responsible for activating itself. For this purpose the class needs a field to keep its activator. This field is only used by the <a href="../transparent_activation_framework.htm">transparent activation framework</a>. Therefore it's marked as transient, to avoid that it's stored in the database. </p> <div class="codesnippet" MadCap:conditions="Primary.c#"> <pre class="prettyprint" xml:space="preserve">public class Person : IActivatable { [NonSerialized] private IActivator activator;</pre> <div class="codesnippet-meta">Person.cs: Implement the required activatable interface and add activator <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-csharp.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <div class="codesnippet" MadCap:conditions="Primary.VB.NET"> <pre class="prettyprint lang-vb" MadCap:conditions="Primary.Online" xml:space="preserve">Public Class Person Implements IActivatable <Transient()> _ Private m_activator As IActivator</pre> <div class="codesnippet-meta">Person.vb: Implement the required activatable interface and add activator <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-vb.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <p>Then implement the two methods of the <span class="PrimaryActivatable">IActivatable</span>-interface. The bind-method binds an activator to the object. It's called by the transparent activation framework. The activate-method needs to be called before any read or write operation on the object. Since these two methods are always the same, you can move the implementation to a common super class or to a static utility class.</p> <div class="codesnippet" MadCap:conditions="Primary.c#"> <pre class="prettyprint" xml:space="preserve">public void Bind(IActivator activator) { if (this.activator == activator) { return; } if (activator != null && null != this.activator) { throw new InvalidOperationException("Object can only be bound to one activator"); } this.activator = activator; } public void Activate(ActivationPurpose activationPurpose) { if (null != activator) { activator.Activate(activationPurpose); } } </pre> <div class="codesnippet-meta">Person.cs: Implement the activatable interface methods <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-csharp.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <div class="codesnippet" MadCap:conditions="Primary.VB.NET"> <pre class="prettyprint lang-vb" MadCap:conditions="Primary.Online" xml:space="preserve">Public Sub Bind(ByVal activator As IActivator) _ Implements IActivatable.Bind If m_activator Is activator Then Exit Sub End If If activator IsNot Nothing AndAlso m_activator IsNot Nothing Then Throw New InvalidOperationException("Object can only be bound to one activator") End If m_activator = activator End Sub Public Sub Activate(ByVal activationPurpose As ActivationPurpose) _ Implements IActivatable.Activate If m_activator IsNot Nothing Then m_activator.Activate(activationPurpose) End If End Sub </pre> <div class="codesnippet-meta">Person.vb: Implement the activatable interface methods <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-vb.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <p>Now the important part. Every time a field of the class is accessed you need to call the activate-method with the purpose. For example in every <span class="Primarygetter/setter">property</span> or other method. Probably the best way is to use only <![CDATA[ ]]><span class="Primarygetter/setter">property</span> <![CDATA[ ]]>even within the class to access fields. And the <span class="Primarygetter/setter">property</span> ensures that the activate-method is called.</p> <div class="codesnippet" MadCap:conditions="Primary.c#"> <pre class="prettyprint" xml:space="preserve">public string Name { get { Activate(ActivationPurpose.Read); return name; } set { Activate(ActivationPurpose.Write); name = value; } } public override string ToString() { // use the getter/setter withing the class, // to ensure the activate-method is called return Name; } </pre> <div class="codesnippet-meta">Person.cs: Call the activate method on every field access <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-csharp.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <div class="codesnippet" MadCap:conditions="Primary.VB.NET"> <pre class="prettyprint lang-vb" MadCap:conditions="Primary.Online" xml:space="preserve">Public Property Name() As String Get Activate(ActivationPurpose.Read) Return m_name End Get Set(ByVal value As String) Activate(ActivationPurpose.Write) m_name = value End Set End Property Public Overloads Overrides Function ToString() As String ' use the getter/setter withing the class, ' to ensure the activate-method is called Return Name End Function </pre> <div class="codesnippet-meta">Person.vb: Call the activate method on every field access <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-vb.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <p> Implementing the <span class="PrimaryActivatable">IActivatable</span>-interface manually for every class is repetitive and error prone. That's why this process can be automated. <a href="ta_enhanced_example.htm" target="" title="" alt="" class="MCXref">See "TA Enhanced Example"</a></p> <p>The last step is to enable transparent persistence via configuration.</p> <div class="codesnippet" MadCap:conditions="Primary.c#"> <pre class="prettyprint" xml:space="preserve">IEmbeddedConfiguration configuration = Db4oEmbedded.NewConfiguration(); configuration.Common.Add(new TransparentActivationSupport()); IObjectContainer container = Db4oEmbedded.OpenFile(configuration, DatabaseFileName);</pre> <div class="codesnippet-meta">TransparentActivationExamples.cs: Activate transparent activation <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-csharp.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <div class="codesnippet" MadCap:conditions="Primary.VB.NET"> <pre class="prettyprint lang-vb" MadCap:conditions="Primary.Online" xml:space="preserve">Dim configuration As IEmbeddedConfiguration = Db4oEmbedded.NewConfiguration() configuration.Common.Add(New TransparentActivationSupport()) Dim container As IObjectContainer = Db4oEmbedded.OpenFile(configuration, DatabaseFileName)</pre> <div class="codesnippet-meta">TransparentActivationExamples.vb: Activate transparent activation <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-vb.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <p>Now transparent persistence is enabled. Now you can navigate the object-graph as deep as you want. The transparent activation will load the objects from the database as you need them.</p> <div class="codesnippet" MadCap:conditions="Primary.c#"> <pre class="prettyprint" xml:space="preserve">using (IObjectContainer container = OpenDatabaseTA()) { Person person = Person.PersonWithHistory(); container.Store(person); } using (IObjectContainer container = OpenDatabaseTA()) { Person person = QueryByName(container, "Joanna the 10"); Person beginOfDynasty = person.Mother; // With transparent activation enabled, you can navigate deeply // nested object graphs. db4o will ensure that the objects // are loaded from the database. while (null != beginOfDynasty.Mother) { beginOfDynasty = beginOfDynasty.Mother; } Console.WriteLine(beginOfDynasty.Name); // Updating a object doesn't requires no store call. // Just change the objects and the call commit. beginOfDynasty.Name = "New Name"; container.Commit(); }</pre> <div class="codesnippet-meta">TransparentActivationExamples.cs: Transparent activation in action <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-csharp.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <div class="codesnippet" MadCap:conditions="Primary.VB.NET"> <pre class="prettyprint lang-vb" MadCap:conditions="Primary.Online" xml:space="preserve">Using container As IObjectContainer = OpenDatabaseTA() Dim joanna As Person = Person.PersonWithHistory() container.Store(joanna) End Using Using container As IObjectContainer = OpenDatabaseTA() Dim joanna As Person = QueryByName(container, "Joanna the 10") Dim beginOfDynasty As Person = joanna.Mother ' With transparent activation enabled, you can navigate deeply ' nested object graphs. db4o will ensure that the objects ' are loaded from the database. While beginOfDynasty.Mother IsNot Nothing beginOfDynasty = beginOfDynasty.Mother End While Console.WriteLine(beginOfDynasty.Name) ' Updating a object doesn't requires no store call. ' Just change the objects and the call commit. beginOfDynasty.Name = "New Name" container.Commit() End Using</pre> <div class="codesnippet-meta">TransparentActivationExamples.vb: Transparent activation in action <div class="codedownload"><a href="../../../CodeExamples/ta/example/Example-ta-example-vb.zip" class="codedownload" MadCap:conditions="Primary.Online">Download Code</a></div><div class="codedownload copylink-marker" MadCap:conditions="Primary.Online"><a href="#copy">Copy Code</a></div></div> </div> <script type="text/javascript" src="../../../SkinSupport/MadCapBodyEnd.js"> </script> </body> </html>