<?xml version="1.0"?>
<!-- RSS generated by Radio UserLand v8.0.8 on Wed, 18 Jan 2006 00:48:48 GMT -->
<rss version="2.0">
	<channel>
		<title>Malcolm Groves: ECO</title>
		<link>http://www.malcolmgroves.com/categories/eco/</link>
		<description></description>
		<copyright>Copyright 2006 Malcolm Groves</copyright>
		<lastBuildDate>Wed, 18 Jan 2006 00:48:48 GMT</lastBuildDate>
		<docs>http://backend.userland.com/rss</docs>
		<generator>Radio UserLand v8.0.8</generator>
		<managingEditor>mgroves@getridofthis.borland.com</managingEditor>
		<webMaster>mgroves@getridofthis.borland.com</webMaster>
		<category domain="http://www.weblogs.com/rssUpdates/changes.xml">rssUpdates</category> 
		<ttl>60</ttl>
		<item>
			<title>ECO III at ADUG Sydney</title>
			<link>http://www.malcolmgroves.com/categories/eco/2006/01/18.html#a131</link>
			<description>&lt;P&gt;I&apos;ll be showing off some of the new features of ECO III at tonight&apos;s &lt;A href=&quot;http://www.adug.org.au/meetings/syd/next_meeting.htm&quot;&gt;ADUG (Australian Delphi User Group) Sydney&lt;/A&gt; meeting. &lt;/P&gt;
&lt;P&gt;It&apos;s essentially a repeat of my Borcon US session. Borland will be providing the pizza and drinks, so come along if you can.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2006/01/18.html#a131</guid>
			<pubDate>Wed, 18 Jan 2006 00:48:47 GMT</pubDate>
			</item>
		<item>
			<title>ECO is Child&apos;s Play</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/10/26.html#a127</link>
			<description>&lt;P&gt;I saw the rough recordings of &lt;A href=&quot;http://bdn.borland.com/article/0,1410,33331,00.html&quot;&gt;this&lt;/A&gt; awhile back, but I just watched it again now that it&apos;s been posted on BDN.&lt;/P&gt;
&lt;P&gt;I thought I was getting reasonably good at explaining this ECO thing, but I bow to the master (mistress?)&lt;/P&gt;
&lt;P&gt;&lt;A href=&quot;http://bdn.borland.com/article/0,1410,33331,00.html&quot;&gt;&lt;a href=&quot;http://bdn.borland.com/article/0,1410,33331,00.html&quot;&gt;http://bdn.borland.com/article/0,1410,33331,00.html&lt;/a&gt;&lt;/A&gt;&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/10/26.html#a127</guid>
			<pubDate>Wed, 26 Oct 2005 05:39:09 GMT</pubDate>
			</item>
		<item>
			<title>Centillex ECOAccess</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/09/29.html#a126</link>
			<description>One of the things I&apos;ve added to my &quot;Things to tinker with when I get time&quot; list is this ECO add-on from Thailand: &lt;BR&gt;&lt;BR&gt;
&lt;DIV style=&quot;MARGIN-LEFT: 40px&quot;&gt;&lt;SPAN style=&quot;FONT-STYLE: italic&quot;&gt;&lt;A href=&quot;http://www.centillex.com/ecoaccess/&quot;&gt;Centillex EcoAccess&lt;/A&gt; is a free library to enable declarative data access services for Borland ECO. It provides flexibilities to declare methods for querying or accessing ECO objects via OCL expression.&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/DIV&gt;OK, so that meant bugger all to me as well when I read it, but looking at the code in the &lt;A href=&quot;http://www.centillex.com/ecoaccess/&quot;&gt;tutorials&lt;/A&gt; on the site, it makes a bit more sense. &lt;BR&gt;&lt;BR&gt;Still not sure if I&apos;d use it or not, but their use of attributes has got me curious. Worth a couple of hours playing with it to see, I think.&lt;BR&gt;&lt;SPAN style=&quot;FONT-STYLE: italic&quot;&gt;&lt;/SPAN&gt;
&lt;DIV style=&quot;MARGIN-LEFT: 40px&quot;&gt;&lt;/DIV&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/09/29.html#a126</guid>
			<pubDate>Wed, 28 Sep 2005 23:20:42 GMT</pubDate>
			</item>
		<item>
			<title>This one&apos;s going straight into the pool room</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/09/26.html#a125</link>
			<description>&lt;p&gt;I spoke with Matthew Overington, a journalist in Australia, a little while back about Model Driven Development in general, and &lt;a href=&quot;http://www.borland.com/us/products/delphi/eco.html&quot;&gt;ECO&lt;/a&gt; in particular. The resulting &lt;a href=&quot;http://www.builderau.com.au/architect/sdi/soa/Model_Driven_Development_today/0,39024602,39205342,00.htm&quot;&gt;article&lt;/a&gt; showed up on BuilderAU back in August.&lt;/p&gt;
&lt;p&gt;I wouldn&apos;t normally post links to sites that have linked to an
article I&apos;m in, but I&apos;m so tickled by this one, I just had to post. The
article has been referenced on the Healthy Hair website, specifically
on the &lt;a href=&quot;http://hairloss.look-4.com/blog/134&quot;&gt;Hair Loss blog&lt;/a&gt; (Who knew there was a blog about hair loss? Why wasn&apos;t I told?). &lt;/p&gt;
&lt;p&gt;Now the less kind amongst you who know what I look like, will no
doubt be able to construct some terribly amusing reason why I&apos;d be on
this site. Oh, how we&apos;d laugh! Sorry to spoil it for you, but you&apos;d be
wrong. There were no photos in the article. Ha!&lt;/p&gt;
&lt;p&gt;My mum will be so proud. I&apos;m not even upset that they messed up the quote. This one&apos;s going straight into the pool room.&lt;/p&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/09/26.html#a125</guid>
			<pubDate>Mon, 26 Sep 2005 03:46:28 GMT</pubDate>
			</item>
		<item>
			<title>Real life complexity with ECOII. Part 1</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/09/19.html#a121</link>
			<description>Hans Karlsen has published the &lt;A href=&quot;http://bdn.borland.com/article/0,1410,33092,00.html&quot;&gt;first&lt;/A&gt; in&amp;nbsp;a series of articles covering his use of ECO II to deal with more real world complexity. Good stuff, especially if you&apos;ve been wondering about Nestings.</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/09/19.html#a121</guid>
			<pubDate>Mon, 19 Sep 2005 00:35:05 GMT</pubDate>
			</item>
		<item>
			<title>ECO : Autoforms and Form Factories</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/08/29.html#a118</link>
			<description>&lt;P&gt;I&apos;ve been in New Zealand this week doing some Borland Developer Day&apos;s events. Mornings we&apos;ve been focusing on ECO, afternoons we&apos;ve been focusing on the new MDA features in the next version of Together.&lt;/P&gt;
&lt;P&gt;Anyway, during the ECO session in Wellington, I was talking about the AutoForms capabilities, and how you could register your own AutoForms for specific types. This is a really useful feature, as you can use the default AutoForm during early parts of your development, so that you can focus on getting the model developed, and then when ready, you can create custom forms to be used to view and edit your objects. Registering them with the AutoForm service means that you don&apos;t have to change any of the code in your app that display&apos;s your AutoForm, it will automatically use the new form you have registered.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=346 src=&quot;http://www.malcolmgroves.com/2005/08/4.png&quot; width=300 border=0&gt;&lt;/P&gt;
&lt;P&gt;After the session, one of the guys in the audience who&apos;d been using ECO for awhile came up to me asked how to do this. To be honest, I thought I&apos;d already blogged about this. Apparently not, so I had a few hours to kill in the Qantas lounge in Christchurch while I waited for my flight home, so I thought I&apos;d write something up. You can grab the sample code &lt;A href=&quot;http://www.malcolmgroves.com/2005/08/ECOAutoForms.zip&quot;&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;A few things first. If you haven&apos;t seen the default AutoForm capabilities, download the source for this project and open it in Delphi 2005 Architect. Bring up Winform1, and note that I&apos;ve set the ECOAutoForm property on the grdAllPeople DataGrid to True. Now I can simply double-click on a row in my grid, and an autoform will be created.&amp;nbsp; This is probably the simplest way to get ECO to display an AutoForm for an object.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=117 src=&quot;http://www.malcolmgroves.com/2005/08/1.png&quot; width=641 border=0&gt;&lt;/P&gt;
&lt;P&gt;NB: If you can&apos;t see an ECOAutoForm property in the DataGrid&apos;s on your form, you probably need to add an ECOAutoFormExtender component to the form. This will insert some ECO-specific properties into the DataGrid.&lt;/P&gt;
&lt;P&gt;Also click on Button3, which is the button labeled &quot;Show&amp;nbsp; Autoform&quot; next to the upper grid. I&apos;ve also set it to display an AutoForm for the currently selected Person in the grid. I&apos;ve enabled this by setting it&apos;s ECOListAction property to ShowAutoForm, and setting its BindingContext to my grdAllPeople grid, and its RootHandle property to the ExpressionHandle holding the collection of Person objects, in this case, ehAllPeople. This is probably the second simplest way to display an AutoForm for an object.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=217 src=&quot;http://www.malcolmgroves.com/2005/08/2.png&quot; width=729 border=0&gt;&lt;/P&gt;
&lt;P&gt;If you want to display an autoform for an ECO object via some other method (e.g., via a context menu, etc), then the following code (Which is also in the Click event of Button4 in the sample project) will achieve the desired result:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=2&gt;procedure TWinForm1.Button4_Click(sender: System.Object; e: System.EventArgs);&lt;BR&gt;var&lt;BR&gt;&amp;nbsp; autoContainer: IAutoContainer;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; if Assigned(cmhSelectedAppointment.Element) then&lt;BR&gt;&amp;nbsp; begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; autoContainer := AutoContainerService.Instance.CreateContainer(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmhSelectedAppointment.Element,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoContainerArgs.Create(EcoSpace,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; False,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AutoContainerMemberVisibility.AllMembers,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ContainerReusage.NeverReuse));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if Assigned(autoContainer) then&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Form(autoContainer).Show;&lt;BR&gt;&amp;nbsp; end;&lt;BR&gt;end;&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Firstly, we&apos;re checking that an Appointment object has been selected in our grid, by seeing if the Element attribute of our CurrencyManagerHandle is assigned. Then, we&apos;re using the AutoContainerService&apos;s CreateContainer method to get back a reference to an IAutoContainer for the selected Appointment. Lastly, provided we got back a reference, we&apos;re casting it as a Form and calling show to display it.&lt;/P&gt;
&lt;P&gt;Running the project should show that clicking the button to invoke this code has the same result as double clicking in the grid. &lt;/P&gt;
&lt;P&gt;Personally any time I want to display a form in my ECO apps, I use this code. Yes, it&apos;s longer than just creating an instance of a custom form and assigning the ECOSpace and the ECO object you want to edit. However, bear with me for a minute and hopefully you&apos;ll see the advantage.&lt;/P&gt;
&lt;P&gt;Open the fAppointmentAutoForm unit and have a look at the TAppointmentForm it contains. I designed this form like I would design any other ECO Winforms. File | New | Other...ECO Enabled Windows Form, drop my controls down. set the ReferenceHandle&apos;s ECOSpaceType and StaticValueTypeName properties, set up my databinding, etc. To convert this form into an ECO AutoForm, I have to do a few things:&lt;/P&gt;
&lt;P&gt;1. Extend your form class so that it implements the IAutoContainer interface. You&apos;ll need to add the Borland.Eco.AutoContainers and the Borland.Eco.ObjectRepresentation namespaces to your interface uses clause. Use Ctrl-Space from within your class declaration to declare the BuildControls, HookUpGUI and set_ECOSpace methods, and extend the declaration of your EcoSpace property so that has a setter method (the aforementioned set_EcoSpace).&lt;/P&gt;
&lt;P&gt;2. Ctrl-Shift-C from inside the form classes declaration to stub out the implementations of these new methods. The code within them looks like the following:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=2&gt;procedure TAppointmentForm.set_EcoSpace(value: EcoSpace);&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; if value &amp;lt;&amp;gt; FEcoSpace then&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FEcoSpace := value;&lt;BR&gt;end;&lt;BR&gt;&lt;BR&gt;procedure TAppointmentForm.HookUpGUI(ecoSpace: EcoSpace; element: IElement);&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; FEcoSpace := ecoSpace;&lt;BR&gt;&amp;nbsp; RHRoot.EcoSpace := self.EcoSpace;&lt;BR&gt;&amp;nbsp; RHRoot.SetElement(element);&lt;BR&gt;end;&lt;BR&gt;&lt;BR&gt;procedure TAppointmentForm.BuildControls(element: IElement;&lt;BR&gt;autoContainerArgs: AutoContainerArgs);&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; &lt;a href=&quot;//&quot;&gt;//&lt;/a&gt; don&apos;t need to do anything, unless you intend writing a generic&lt;BR&gt;&amp;nbsp; &lt;a href=&quot;//&quot;&gt;//&lt;/a&gt; autoform&lt;BR&gt;end;&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Most of these should be fairly self explanatory. The BuildControls method is empty, however if you wanted to dynamically create controls on your AutoForm, this is where you&apos;d do it. &lt;/P&gt;
&lt;P&gt;3. So, now our AutoForm is complete, however we need to register it with the AutoFormService. To do ths, we define a simple Factory class. In the same unit, you&apos;ll see this under my form declaration. Its delcaration looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=2&gt;AppointmentAutoContainerFactory = class(System.Object, IAutoContainerFactory)&lt;BR&gt;public&lt;BR&gt;&amp;nbsp; function get_AutoContainer: IAutoContainer;&lt;BR&gt;&amp;nbsp; function Matches(modelElement: IModelElement): Boolean;&lt;BR&gt;end;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Its implementation looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=2&gt;function AppointmentAutoContainerFactory.get_AutoContainer: IAutoContainer;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; Result := TAppointmentForm.Create(nil);&lt;BR&gt;end;&lt;BR&gt;&lt;BR&gt;function AppointmentAutoContainerFactory.Matches(modelElement: IModelElement): Boolean;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; Result := modelElement.Name.Equals(Appointment.ClassName);&lt;BR&gt;end;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;You may need to add the Borland.Eco.UmlRt namespace to your Interface uses clause. The get_AutoContainer method is where we actually create an instance of our form. The Matches method will be called by the ECO Framework, passing in a reference to the model element for which it is trying to create an AutoForm. Your job in this method is to decide if your form will handle this class, in this case I&apos;m checking whether it represents an Appointment, and if so returning true.&lt;/P&gt;
&lt;P&gt;4. Lastly, I need to register my Factory with the AutoForm service, by adding the following code to the initialization section of the unit:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=2&gt;initialization&lt;BR&gt;&amp;nbsp;AutoContainerService.Instance.AddFactory(AppointmentAutoContainerFactory.Create);&lt;BR&gt;finalization&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;That&apos;s it. Now when you run your app, you should notice that when you request an autoform for an Appointment object you&apos;ll get back our new form. This is regardless of how you request it (i.e.. double clicking in your grid, using the ECOListAction on your button, using the AutoForm code, ECOSpaceDebugger etc). You don&apos;t need to change any of your forms, you can make the change in one place and the rest of your app will follow. Way cool!&lt;/P&gt;
&lt;P&gt;In the &lt;A href=&quot;http://www.malcolmgroves.com/2005/08/ECOAutoForms.zip&quot;&gt;sample code&lt;/A&gt;, the initialization section code is commented out, so you can easily see the before and after effect.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=622 src=&quot;http://www.malcolmgroves.com/2005/08/3.png&quot; width=830 border=0&gt;&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/08/29.html#a118</guid>
			<pubDate>Mon, 29 Aug 2005 00:32:46 GMT</pubDate>
			</item>
		<item>
			<title>24 hours of Delphi</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/07/13.html#a116</link>
			<description>So, we&apos;re getting close to the 24 hours of Delphi online radio thingy
(yes, I think that&apos;s the official name). The schedule is up &lt;a href=&quot;http://bdn.borland.com/article/0,1410,33109,00.html&quot;&gt;here&lt;/a&gt;.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
I&apos;m going to be on at midnight PST, and then again at 11pm PST (which
thankfully is a much more civilised 5pm and 4pm respectively where I
am), but I&apos;ll be sticking my head in whenever I can. I&apos;ll also be
making an effort to be online for the ECO bits, which are:&lt;br&gt;
&lt;br&gt;
&lt;ul&gt;
  &lt;li&gt;3:00 am PST with Jan&lt;/li&gt;
  &lt;li&gt;3:45 am PST with Jonas&lt;/li&gt;
  &lt;li&gt;10:00 am PST with Daniel&lt;/li&gt;
  &lt;li&gt;7:00 pm pST with Randy&lt;/li&gt;
  &lt;li&gt;10:00pm with Tim and Dick&lt;/li&gt;
&lt;/ul&gt;
Hmm and Brian Long is always good value, and Marco, and..., OK, looks
like I&apos;m not going to get much work done for the next 24 hours.&lt;br&gt;
</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/07/13.html#a116</guid>
			<pubDate>Tue, 12 Jul 2005 23:07:56 GMT</pubDate>
			</item>
		<item>
			<title>OCL : subSequence</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/07/04.html#a114</link>
			<description>I think I&apos;ve mentioend before that I&apos;ve been working on an internal
website using ASP.NET and ECO II. Partly because replacing the current
site (based on static HTML) is going to make my life a lot easier, but
also as I kinda miss coding as a day job, and of course if you want to
really learn a new technology like ECO, there&apos;s no substitute for
actually building and deploying an app into production.&lt;br&gt;
&lt;br&gt;
Anyway, one of the things I wanted to do was to display summary lists
of items on the main page of the site. You know, recently posted items,
important upcoming dates, last 10 posts to the SE mailing list, etc.
Most of this is easy, OCL like the following will pull out all Items in
reverse order (ie. most newest to oldest).&lt;br&gt;
&lt;br&gt;
Item.allInstances-&amp;gt;orderdescending(ModifiedTime)&lt;br&gt;
&lt;br&gt;
Problem is, I don&apos;t want to display all Items, only the most recent items, say, the last 10. Enter the subSequence operator:&lt;br&gt;
&lt;br&gt;
Item.allInstances-&amp;gt;orderdescending(ModifiedTime)-&amp;gt;subSequence(1,10)&lt;br&gt;
&lt;br&gt;
With this, I have a list of 10 Items, starting at position 1 in my list of Items ordered by ModifiedTime. Perfect!&lt;br&gt;

</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/07/04.html#a114</guid>
			<pubDate>Mon, 04 Jul 2005 00:43:17 GMT</pubDate>
			</item>
		<item>
			<title>ECOSpaceDebugger</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/06/08.html#a111</link>
			<description>&lt;P&gt;ECO lets you move from building your model to executing and&amp;nbsp;interacting with that model incredibly quickly. The model-aware framework with its databinding support, autoforms capabilities, etc mean you can build UI&apos;s that let you play with your model faster than any other tool. &lt;/P&gt;
&lt;P&gt;However, ungrateful bugger that I am, I&apos;m now spoiled and&amp;nbsp;&quot;incredibly quickly&quot; just isn&apos;t fast enough anymore. What I want is a way to create my model, and without setting up anything, I want to be able to interact with it. Or more often, change my model, and test out my changes immediately, without adding the necesary UI bits until I know that it works how I want it to work.&lt;/P&gt;
&lt;P&gt;Well, lurking away in a dark corner of the ECO Framework is something that gets me very close to that. The ECOSpace Debugger gives you a UI that lets you, amongst other things:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;create, edit&amp;nbsp;and delete instances of objects in your model 
&lt;LI&gt;bring up autoforms for an object 
&lt;LI&gt;set Checkpoints, then undu and redo changes 
&lt;LI&gt;start, commit and rollback object transactions&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2005/06/08/20050608001.jpg&quot; border=0&gt;&lt;/P&gt;
&lt;P&gt;At the moment you still need to write the code to invoke the ECOSpace Debugger, but it&apos;s only a couple of lines, so that&apos;s still pretty amazing.&lt;/P&gt;
&lt;P&gt;Here&apos;s the steps to try it out:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Create a new Winforms ECO app 
&lt;LI&gt;Define&amp;nbsp;a few classes and associations in your model 
&lt;LI&gt;Add the &lt;FONT face=&quot;Courier, Monospace&quot;&gt;Borland.ECO.Diagnostics&lt;/FONT&gt; namespace to your mainform&apos;s uses clause. 
&lt;LI&gt;Drop a button on your mainform, and in the Click event add the following code:&lt;/LI&gt;&lt;/UL&gt;
&lt;BLOCKQUOTE dir=ltr style=&quot;MARGIN-RIGHT: 0px&quot;&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot;&gt;EcoSpaceDebugger.Create(EcoSpace).Show;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P dir=ltr&gt;That&apos;s it! Run your app, click the button, and you can start playing with your model. Change your model, run the app again and interact with your changes. How simple is that?&lt;/P&gt;
&lt;P dir=ltr&gt;If you want to have a bit more of a sniff around, double-click on the Borland.Eco.Windows.Forms.dll in the References section of the Project manager, and drill down into the Borland.Eco.Diagnostics namespace using the&amp;nbsp;Reflection tool built into the IDE. &lt;/P&gt;
&lt;P dir=ltr&gt;I did say I was ungrateful. Now that I have this, I want&amp;nbsp;to&amp;nbsp;get rid of that button and line of source. Like&amp;nbsp;maybe by creating a&amp;nbsp;non-visual component that shows the debugger on create, if a boolean property is set to true. Hmmm, maybe on my next flight...&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/06/08.html#a111</guid>
			<pubDate>Wed, 08 Jun 2005 11:04:43 GMT</pubDate>
			</item>
		<item>
			<title>Custom OCL Operations</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/04/20.html#a109</link>
			<description>&lt;A href=&quot;http://blogs.borland.com/jonashogstrom/&quot;&gt;Jonas&lt;/A&gt; has just updated the ECO pmwiki with an interesting post on creating &lt;A href=&quot;http://homepages.borland.com/ecoteam/pmwiki/pmwiki.php?n=Eco.CustomOclOperations&quot;&gt;custom OCL operations&lt;/A&gt;, along with an example that implements a bunch of DateTime functionality that you can invoke from OCL. One of the guys mentioned this a few months back, and I&apos;ve been waiting since then to get my hands on it. Hmmm, wonder if I have time to play tonight.....</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/04/20.html#a109</guid>
			<pubDate>Tue, 19 Apr 2005 20:56:40 GMT</pubDate>
			</item>
		<item>
			<title>ECO is Love</title>
			<link>http://www.malcolmgroves.com/categories/eco/2005/04/14.html#a107</link>
			<description>&lt;P&gt;Part of the reason I&apos;ve been quiet on the blog lately (apart from work, travel, family life, ill dogs, and just general laziness) is that I&apos;ve been working on a reasonably large ECO/ASP.NET application for use internally in Borland. Eventually I&apos;d like to publish the source code (inspired as I am by Peter Morris) but trust me, you wouldn&apos;t want to see it in its current state.&lt;/P&gt;
&lt;P&gt;Anyway, back to the point. Being a web app, part of it follows a fairly common web standard of organising content in a hierarchy of categories that users can use to navigate down into more specific areas. Think of the directory structure at Yahoo in the screenshot below&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2005/04/14/20050414001.gif&quot; border=0&gt;&lt;/P&gt;
&lt;P&gt;Anyway, this was relatively easy to implement in a model: a Category class that has an auto-association (ie. an association to itself) such that a Category can have 0..* child categories, and a Category can have 0..1 parent categories. It was also relatively easy to set up in ASP.NET so I could browse my way up and down these categories.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2005/04/14/20050414002.gif&quot; border=0&gt;&lt;/P&gt;
&lt;P&gt;What had me stumped for awhile were the breadcrumbs. Breadcrumbs? Look in the Yahoo screenshot above. Near the top, it has a list of all the ancestor categories as links, so you can work your way back up to where you came from.&amp;nbsp; I wanted to be able to get a list of the Category objects that make up the path from a specific Category all the way to the root. In the screenshot, it&apos;s Directory, Computers and Internet, Programming and Development, Languages, Delphi from least specific down to most specific. Once I had this in a handle, I could bind it to an ASP.NET Repeater component and Robert&apos;s your mother&apos;s brother. I didn&apos;t only need to access this path for the breadcrumbs, but that&apos;s a nice, visible example of what I needed. &lt;/P&gt;
&lt;P&gt;I eventually came up with some fairly convoluted code that walked up the Parent association, adding each to a handle as I went (which involved some pretty funky casting along the way).&amp;nbsp;That worked, but it left a fairly foul taste in my mouth. I thought ECO was supposed to stop me from having to write this sort of pointless plumbing code?&lt;/P&gt;
&lt;P&gt;Well, obviously if there wasn&apos;t a better way I wouldn&apos;t be writing this article. After some help from &lt;A href=&quot;http://blogs.borland.com/jesperhogstrom/&quot;&gt;Jesper&lt;/A&gt; and &lt;A href=&quot;http://blogs.borland.com/jonashogstrom/&quot;&gt;Jonas&lt;/A&gt; (thanks guys!) here&apos;s my current solution. I&apos;m sure there are others, but I&apos;m kinda fond of this one at the moment.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2005/04/14/20050414003.gif&quot; border=0&gt;&lt;/P&gt;
&lt;P&gt;I&apos;ve added a &lt;A href=&quot;http://www.malcolmgroves.com/categories/eco/2004/04/30.html#a60&quot;&gt;Derived Association&lt;/A&gt;, in fact another auto-association, called Path and made it uni-directional. When you reference this association you should get back all categories from the root down to the current Category. To make this happen, the Derivation OCL for the Path association looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier New&quot; size=3&gt;if self.Parent.isNull then &lt;BR&gt;&amp;nbsp; self-&amp;gt;asSet &lt;BR&gt;else &lt;BR&gt;&amp;nbsp; self.Parent.Path-&amp;gt;including(self) &lt;BR&gt;endif&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If the current Category is the root, its Parent will be null, and as a result we return a collection of just the current Category. However, if we are somewhere down the tree, then we use the &lt;FONT face=&quot;Courier New&quot;&gt;including&lt;/FONT&gt; operator to add the current Category to its Parent&apos;s Path collection (ie. we&apos;re recursively calling this derived association).&lt;/P&gt;
&lt;P&gt;Works like a bought one, as you can see in the screenshot below. The top left grid is showing all the Category objects, and also serves to let us select a particular category. The bottom left grid is showing the children of the currently selected Category, and the bottom right grid is showing the contents of the currently selected Category&apos;s Path association. Exactly what I needed.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2005/04/14/20050414004.gif&quot; border=0&gt;&lt;/P&gt;
&lt;P&gt;Yes, the result is exactly the same as my convoluted code, and yes I had to learn a bit of OCL (&lt;A href=&quot;http://www.viewpointsa.com/bold_resources/getting_started_with_bold/Part3-OCL.html&quot;&gt;this&lt;/A&gt; is the best OCL reference I&apos;ve found so far, BTW. Thank you Anthony), but it just feels so much more ECO-like to be able to tell the framework what I want at a higher level, rather than&amp;nbsp;having&amp;nbsp;to&amp;nbsp;explicitly say how to do it. Sure, I always want to have the option to take&amp;nbsp;control over how things happen, but for stuff like this, I couldn&apos;t care less.&lt;/P&gt;
&lt;P&gt;&amp;lt;Sigh&amp;gt; Once again I&apos;m reminded, ECO is love.&lt;/P&gt;
&lt;P&gt;Oh, you can download the source for this example &lt;A href=&quot;http://www.malcolmgroves.com/images/2005/04/14/ECOHirearchyTest.zip&quot;&gt;here&lt;/A&gt; (and yes, I realise I can&apos;t spell, but then Delphi doesn&apos;t spell check my Project names for me, so it&apos;s not my fault).&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2005/04/14.html#a107</guid>
			<pubDate>Thu, 14 Apr 2005 06:44:48 GMT</pubDate>
			</item>
		<item>
			<title>WooHoo! An ECO blog from a non-Borlander</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/12/22.html#a105</link>
			<description>&lt;P&gt;I have a page in OneNote where I grab snippets of newsgroup conversations, emails, etc about ECO that I store away for future reference. The title of this page is &quot;ECO Gems&quot;. Well, I just looked through it and a high percentage of my ECO Gems&amp;nbsp;are from Peter Morris.&lt;/P&gt;
&lt;P&gt;Why do you care? Well, Peter has started a&amp;nbsp;&lt;A href=&quot;http://blogs.slcdug.org/petermorris/&quot;&gt;blog&lt;/A&gt;. Definitely subscribed!&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/12/22.html#a105</guid>
			<pubDate>Wed, 22 Dec 2004 05:06:49 GMT</pubDate>
			</item>
		<item>
			<title>ECO 2 Under The Hood</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/10/28.html#a97</link>
			<description>&lt;P&gt;Has somebody put something in the water over there on the ECO team? Only a couple of days ago &lt;A href=&quot;http://blogs.borland.com/jonashogstrom&quot;&gt;Jonas&lt;/A&gt; kicked off his blog, now &lt;A href=&quot;http://blogs.borland.com/andersivner/archive/2004/10/26.aspx&quot;&gt;Anders&lt;/A&gt; weighs in with hi post on some of the guts of the framework. Cool stuff!&lt;/P&gt;
&lt;P&gt;&lt;A href=&quot;http://blogs.borland.com/JanNorden/&quot;&gt;Jan&lt;/A&gt;? &lt;A href=&quot;http://blogs.borland.com/jesperhogstrom/&quot;&gt;Jesper&lt;/A&gt;? &lt;A href=&quot;http://blogs.borland.com/HenrikJondell/&quot;&gt;Henrik&lt;/A&gt;? Nothing to say? :-)&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/10/28.html#a97</guid>
			<pubDate>Thu, 28 Oct 2004 11:24:31 GMT</pubDate>
			</item>
		<item>
			<title>From the Horses Mouth</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/10/26.html#a96</link>
			<description>&lt;P&gt;That is Jonas&apos;s phrase not mine. &lt;/P&gt;
&lt;P&gt;Anyway, &lt;A href=&quot;http://blogs.borland.com/jonashogstrom&quot;&gt;Jonas&lt;/A&gt; is blogging! Yay! &lt;/P&gt;
&lt;P&gt;I don&apos;t even mind that he pointed out all my mistakes. If it keeps him writing these sorts of useful blogs, I&apos;m happy to keep making mistakes :-)&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/10/26.html#a96</guid>
			<pubDate>Tue, 26 Oct 2004 01:20:27 GMT</pubDate>
			</item>
		<item>
			<title>ECO : OCLPSHandle</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/10/21.html#a94</link>
			<description>&lt;P&gt;So far in my ECO examples, I&apos;ve been ignoring the issue of performance. I&apos;ve been behaving as if my application will perform identically whether I have 10 objects or 1,000,000 objects. Obviously, this is absurd, so I want to start dealing with this issue. There are many things you can do to control the performance of your ECO app, and this first article will look at one of them, specifically the OCLPSHandle.&lt;/P&gt;
&lt;P&gt;Look at the following OCL for example&lt;/P&gt;
&lt;P&gt;Person.allInstances-&amp;gt;select(Age &amp;lt; 18)&lt;/P&gt;
&lt;P&gt;Hopefully by now you recognise that this OCL will return a collection of all Person objects that have the value of their Age attribute less than 18. If we use an ExpressionHandle to execute this OCL, as we have been in all our examples so far, a few things could happen. Firstly, let&apos;s assume that our ECOSpace is empty, so any Person object we wish to access will need to be loaded from the database (we&apos;ll deal later with the case where our ECOSpace is not empty).&lt;/P&gt;
&lt;P&gt;So, how can we see what happens when we request this OCL to be executed? There are a couple of tools that I find useful in this type of situation. One is some sort of&amp;nbsp;SQL monitor, so that&amp;nbsp;I can view the actual SQL being executed by the ECO Framework. The other is the &lt;A href=&quot;http://www.borland.com/opt_profiler/&quot;&gt;OptimizeIt Profiler for .NET&lt;/A&gt;, a CPU and Memory profiler that ships with the Architect edition of Delphi and C#Builder. The Memory Profiler in OptimizeIt allows me to peer inside my ECOSpace and see exactly what objects are in memory. &lt;/P&gt;
&lt;P&gt;Back to our example, however.&amp;nbsp;The ExpressionHandle behavior is that the select filter above will be executed by the ECOSpace. If we look at the contents of our ECOSpace before executing this OCL in an ExpressionHandle we can see that there are no Person objects instantiated (note the filter I have placed in OptimizeIt, allowing me to only view my domain objects). &lt;/P&gt;
&lt;P&gt;&lt;IMG hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/10/21/20041020001.gif&quot; border=0&gt; &lt;/P&gt;
&lt;P&gt;When I execute this OCL using an ExpressionHandle, a number of SQL statements are executed. My example is using SQL Server, and in this case, firstly ECO executes this:&lt;/P&gt;
&lt;P&gt;SELECT BOLD_ID, BOLD_TYPE FROM Person&lt;/P&gt;
&lt;P&gt;Then the BOLD_ID&apos;s returned from this statement are used in the following SQL, to actually return the complete objects:&lt;/P&gt;
&lt;P&gt;SELECT BOLD_ID, BOLD_TYPE, Firstname, Lastname, Age FROM Person WHERE BOLD_ID IN (...)&lt;/P&gt;
&lt;P&gt;where the list of BOLD_ID&apos;s are inserted between the braces after the IN statement.&lt;/P&gt;
&lt;P&gt;Think about this for a moment. This means that all my Person objects will be loaded from my database into my ECOSpace, then the ECOSpace will filter out the correct Person objects and return my collection. While this might be fine for 9 objects as I have, what if I have 10,000 objects, or 100,000, or 1,000,000? This will rapidly become a problem. Just to be sure, this screenshot from OptimizeIt shows that the ECOSpace after this statement is executed holds 9 Person objects, even though my Grid only displays the 2 that match my select statement.&lt;/P&gt;
&lt;P&gt;&lt;IMG hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/10/21/20041020002.gif&quot; border=0&gt; &lt;/P&gt;
&lt;P&gt;&lt;IMG hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/10/21/20041020004.gif&quot; border=0&gt; &lt;/P&gt;
&lt;P&gt;So, how can we exercise some control over this? Well, this is where you can use a component called OCLPSHandle. The PS in the name stands for Persistent Store, because this component will attempt to convert the OCL into a SQL Statement so that the filtering in this case will be executed by the backend database rather than the ECOSpace. So, the exact same OCL as above, but loaded into an OCLPSHandle rather than an ExpressionHandle, results in the following SQL being executed:&lt;/P&gt;
&lt;P&gt;SELECT BOLD_ID FROM Person WHERE (Age &amp;lt; 18)&lt;/P&gt;
&lt;P&gt;Note the very important WHERE clause, which means the database will do the heavy lifting for us and only return the records that match the OCL filter. ECO can then request the full data only for the required objects. Again, OptimizeIt shows us that after this OCL is executed, only the 2 matching objects exist in our ECOSpace.&lt;/P&gt;
&lt;P&gt;&lt;IMG hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/10/21/20041020003.gif&quot; border=0&gt; &lt;/P&gt;
&lt;P&gt;And note the end result in our Grid is the same:&lt;/P&gt;
&lt;P&gt;&lt;IMG hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/10/21/20041020005.gif&quot; border=0&gt; &lt;/P&gt;
&lt;P&gt;Not only is this much more efficient over the network and&amp;nbsp;more efficient in terms of memory, it also executes a lot faster. There are a couple of downsides (c&apos;mon, nothing comes for free). Whereas an ExpressionHandle will execute its OCL automatically, we need to call the OCLPSHandle.Execute method in order for it to execute the OCL and return the result. Still, a small price to pay for such improved performance.&lt;/P&gt;
&lt;P&gt;Secondly, the OCLPSHandle, by its very nature, can only return objects that are stored in the database. If there was a Person object in memory that matched my OCL filter, but that had not yet been persisted to the database, the OCLPSHandle would not by default include that in the resulting collection. This can be worked around of course, and Christophe Floury in his excellent &quot;Unleashing Enterprise Models&quot; (&lt;A href=&quot;http://www.borland.com/products/white_papers/del_csharpbuilder_unleashing_enterprise_models.html&quot;&gt;C#Builder version&lt;/A&gt; / &lt;A href=&quot;http://www.borland.com/products/white_papers/del_unleashing_enterprise_models_with_delphi_for_dotnet.html&quot;&gt;Delphi version&lt;/A&gt;) whitepapers shows example source for this very issue. Basically he uses the OCLPSHandle as above, then interrogates the ECOSpace and adds any Person objects to the resulting collection that have not yet been saved and that match the filter. &lt;/P&gt;
&lt;P&gt;So, we can now deal much more effectively with large numbers of objects. There is more we can do to tweak ECO&apos;s performance, but that will have to wait for a future article.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/10/21.html#a94</guid>
			<pubDate>Wed, 20 Oct 2004 20:24:26 GMT</pubDate>
			</item>
		<item>
			<title>ECO Variables : Part 1</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/08/25.html#a80</link>
			<description>&lt;DIV class=Section1&gt;If you&amp;#146;ve done any Delphi or C#Builder database programming, think about the SQL statements you&amp;#146;ve used. Have you always known all the SQL you want to use at design time? I&amp;#146;m guessing the answer is no. You quite often know most of the statement, but maybe at runtime you have to substitute in some parameters for your Where clause, for example. 
&lt;P&gt;Well, it&amp;#146;s the same thing with OCL. So far we&amp;#146;ve been acting like we can hope to know all the OCL we ever intend to use at design time. Far more common is that you want the same ability to use Parameters in your OCL, just as you do with SQL. However, in ECO they are called Variables, rather than Parameters, but it&amp;#146;s the same concept. They allow us to create OCL that dynamically responds to changes at runtime. &lt;/P&gt;
&lt;P&gt;Let me give you an example. Say we want a search screen, like this:&lt;/P&gt;
&lt;P&gt;&lt;IMG height=296 src=&quot;http://www.malcolmgroves.com/images/2004/08/25/20040825005.gif&quot; width=376 border=0&gt;&lt;/P&gt;
&lt;P&gt;Here I have a grid of Person objects, and some TextBoxes above each field. As I type into one or more of the TextBoxes, the grid only displays the objects that match. How to achieve this? &lt;/P&gt;
&lt;P&gt;Well, with static OCL, one way of achieving the end result would be with OCL like this:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Person.allInstances-&amp;gt;select( Firstname.regExpMatch(&amp;#147;Ja&amp;#148;) and&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Lastname.regExpMatch(&amp;#147;&amp;#148;) and&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Country.regExpMatch(&amp;#147;U&amp;#148;))&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Note that I&amp;#146;m using the select operator, which returns a collection of Person objects that match the Boolean expression inside the brackets. In this case, I&amp;#146;m doing Regular Expression matching&amp;nbsp; on each of the fields in order to return the Boolean expression expected by the select function.&lt;/P&gt;
&lt;P&gt;Well, this will work, but really we want to be able to substitute in the values to match against at runtime. You could build up this string dynamically I guess, then shove it into the ExpressionHandle, but another way is to use Variables. Let&amp;#146;s look at how you do it. &lt;/P&gt;
&lt;P&gt;Apart from the DataGrid and TextBoxes above, you&amp;#146;ll have a ReferenceHandle pointing at your ECOSpace, and an ExpressionHandle connected up to the ReferenceHandle. The DataGrid is connected to your ExpressionHandle. If you&amp;#146;ve worked your way through the tutorials, all of that should not be terribly difficult. Don&amp;#146;t worry about what OCL to put in the ExpressionHandle just yet. &lt;/P&gt;
&lt;P&gt;What we need to do is to take the text entered into the TextBoxes and somehow get it into some OCL. We&amp;#146;ll start with just searching on the Firstname attribute, then look at what you&amp;#146;d do to search on all three.&lt;/P&gt;
&lt;P&gt;Drop down a component called a VariableHandle and name it vhFirstname. The VariableHandle is responsible to holding the value of a Variable we wish to use in our OCL. A VariableHandle is a bit like a ReferenceHandle, in that needs you to give it a reference to your EcoSpace. For the ReferenceHandle, the File | New | Other | ECO Winforms App wizard did this automatically, but for the VariableHandle, you&apos;ll have to do it yourself. &lt;/P&gt;
&lt;P&gt;Two steps are required. Dropdown the VariableHandle&apos;s ECOSpaceType property and select the type of the ECOSpace you are using. Then, have a look in the get_EcoSpace method of our form, and add the line in bold below. Note the Wizard has inserted the equivalent line for the ReferenceHandle (named rhRoot) just above it.&lt;/P&gt;
&lt;P&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;function TWinForm.get_EcoSpace: TECOSimpleSearchEcoSpace;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; if not Assigned(fEcoSpace) then&lt;BR&gt;&amp;nbsp; begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fEcoSpace := TECOSimpleSearchEcoSpace.Create;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rhRoot.EcoSpace := fEcoSpace;&lt;BR&gt;&lt;B&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; vhFirstname.EcoSpace := fEcoSpace;&amp;nbsp; &lt;a href=&quot;//&quot;&gt;//&lt;/a&gt; insert this line&lt;BR&gt;&lt;/B&gt;&amp;nbsp; end;&lt;BR&gt;&amp;nbsp; result := fEcoSpace;&lt;BR&gt;end;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;We also need to specify the type of this Variable. In our case, it&amp;#146;s a string, but it could be a number, a date or time value, etc. Unlike SQL Parameters, it could be even more than this. Our variable could be a collection of strings, dates, etc, an object, or even a collection of objects! Think for awhile about the flexibility that would provide. (For those who don&apos;t want to think about it, don&apos;t worry, I&apos;ll cover it in the next article)&lt;/P&gt;
&lt;P&gt;So, to specify the type of our Variable, we use the VariableHandle&apos;s StaticValueTypeName property. Click on the Ellipsis button for this property and you should see the Type name Selector dialog shown below, which allows you to select the simple type or class, or collection of either, that you want this VariableHandle to hold. In our case, select System.String.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=666 src=&quot;http://www.malcolmgroves.com/images/2004/08/25/20040825003.gif&quot; width=416 border=0&gt;&lt;/P&gt;
&lt;P&gt;OK, so we have a VariableHandle to hold the value entered into the TextBox. How do we get the value in there? Go to the TextBox component, and put the following code into its TextChanged event:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;vhFirstname.Element.AsObject := txtFirstname.Text;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Now, whenever the user changes the text in the TextBox, our VariableHandle component will be updated with the new value. You can replicate this for the other attributes we want to search on (ie. Drop down two more VariableHandles, set their ECOSpaceType and StaticValueTypeName properties, add the relevant code to the get_ECOSpace method, and set up TextChanged events on the relevant TextBoxes so that the variableHandles get updated as the user changes the search text)&lt;/P&gt;
&lt;P&gt;That&amp;#146;s great, but we still have no connection between the VariableHandles and the OCL in our ExpressionHandle. So, to hook them up, we need to drop down an OCLVariables component. This component is responsible for holding a collection of variables used in OCL, and the relevant VariableHandles from which their values should be retrieved. Select the OCLVariable component, and bring up the property editor for the OclVariablesCollection property. Add three members to the collection, and for each one, set the ElementHandle and VariableHandle properties. In the screenshot below, you can see how I&amp;#146;ve set the first one.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=389 src=&quot;http://www.malcolmgroves.com/images/2004/08/25/20040825004.gif&quot; width=487 border=0&gt;&lt;/P&gt;
&lt;P&gt;What this screenshot shows is I&amp;#146;ve created a connection between the vhFirstname VariableHandle component and a Variable called vFirstname. I&amp;#146;ve done the same for LastName and Country. &lt;/P&gt;
&lt;P&gt;The last piece is to connect the ExpressionHandle that is connected to my DataGrid to my OCLVariables component, using the ExpressionHandle&amp;#146;s Variables property. Then, enter the following OCL into your ExpressionHandle:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Person.allInstances-&amp;gt;select( Firstname.regExpMatch(vFirstname) and&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Lastname.regExpMatch(vLastname) and&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: Courier New&quot;&gt;Country.regExpMatch(vCountry))&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And we&amp;#146;re done. In concept, what happens when the OCL is evaluated, is that the OCL Parser will come across vFirstname, and now knowing what that is, will go out to the ExpressionHandle and request the value. It will, using its Variables property, look in the OCLVariables component and see that the value of vFirstname needs to come from the VariableHandle called vhFirstname. This value will be retrieved, and will either be empty or some string value that was assigned when the user typed into the TextBox. This value will be substituted into the OCL. The same happens for the other two variables and we&amp;#146;re away. The image below hopefully clarifies the relationships between the non-visual controls:&lt;/P&gt;
&lt;P&gt;&lt;IMG height=190 src=&quot;http://www.malcolmgroves.com/images/2004/08/25/20040825002.gif&quot; width=400 border=0&gt;&lt;/P&gt;
&lt;P&gt;Now a few things to realize. In this case we&amp;#146;re using variables in the regExpMatch OCL function, but we can use variables in many different OCL expressions. Also, as I mentioned before, our Variable could contain more than a simple data type like a string, maybe a collection or an object (or a collection of objects), and provided that type was valid where you were placing your variable in your OCL, that&amp;#146;s fine. As I mentioned earlier, in the second part of this article I&apos;ll do another example using a collection of objects as a variable, however the steps involved are basically the same, so you can porbably figure it out from here.&lt;/P&gt;&lt;/DIV&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/08/25.html#a80</guid>
			<pubDate>Wed, 25 Aug 2004 12:59:38 GMT</pubDate>
			</item>
		<item>
			<title>Ping</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/06/28.html#a75</link>
			<description>&lt;P&gt;You&apos;d be forgiven for wondering if I was still alive, but life has kinda gotten in the way of blogging over the last few weeks. &lt;/P&gt;
&lt;P&gt;First, my wife and I escaped the winter in Sydney for a 2 week surfing holiday in Bali. Then I returned to work right at the end of quarter, so it&apos;s been a little hectic. &lt;/P&gt;
&lt;P&gt;That said, I have a couple of articles on Variables that are moving towards completion, and also one on Constraints that is less far along. If I can get past Wednesday I&apos;ll get stuck in and finish them off.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/06/28.html#a75</guid>
			<pubDate>Sun, 27 Jun 2004 23:23:27 GMT</pubDate>
			</item>
		<item>
			<title>Evaluate OCL in Code</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/05/31.html#a73</link>
			<description>&lt;P&gt;A quick one for today. &lt;/P&gt;
&lt;P&gt;Just had a question from someone on how to evaluate OCL from code. Assuming you have&amp;nbsp;our Person class from the previous examples, place the following code in a button&apos;s click event:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot; size=1&gt;procedure TWinForm.Button1_Click(sender: System.Object; e: System.EventArgs);&lt;BR&gt;var&lt;BR&gt;&amp;nbsp; OCLResult : IElement;&lt;BR&gt;&amp;nbsp; ObjList : IObjectList;&lt;BR&gt;&amp;nbsp; i : Integer;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; OCLResult := ECOSpace.OclService.EvaluateAndSubscribe(nil, &apos;&lt;STRONG&gt;Person.AllInstances&lt;/STRONG&gt;&apos;,&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face=&quot;Courier, Monospace&quot; size=1&gt;nil, nil);&lt;BR&gt;&amp;nbsp; if OCLResult is IObjectList then&lt;BR&gt;&amp;nbsp; begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ObjList := IObjectList(OCLResult);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot; size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i := 0 to ObjList.Count - 1 do&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MessageBox.Show(Person(ObjList.Item[i].AsObject).Firstname);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end;&lt;BR&gt;&amp;nbsp; end;&lt;BR&gt;end;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here, I&apos;m executing some simple OCL (Person.AllInstances) and then iterating through the resulting collection. The Item property of IObjectList returns an IObject. You can then reference its AsObject method to get back a TObject, which you can cast as your Person and away you go. &lt;/P&gt;
&lt;P&gt;Once you have your Person, dealing with&amp;nbsp;any attributes or associations that it has will be much easier, as they will be correctly typed. It&apos;s just &quot;getting inside&quot;&amp;nbsp;our object model where we need to cast all over the shop.&lt;/P&gt;
&lt;P&gt;Obviously, if your OCL doesn&apos;t return a collection, then you&apos;d deal differently, but the above code should get you started. &lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/05/31.html#a73</guid>
			<pubDate>Mon, 31 May 2004 01:23:27 GMT</pubDate>
			</item>
		<item>
			<title>Optimistic Locking in ECO</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/05/30.html#a70</link>
			<description>&lt;A href=&quot;http://www.borland.com/delphi_net/architect/eco/tutorial/tutorial3.html&quot;&gt;One of the ECO Tutorials&lt;/A&gt; up on the Borland website provides a good introduction to ECO and databases. But I&apos;ve had a couple of different people ask me about how to deal with locking. I&apos;m assuming you&apos;ve read &lt;A href=&quot;http://www.borland.com/delphi_net/architect/eco/tutorial/tutorial3.html&quot;&gt;that tutorial&lt;/A&gt; before reading the rest of this article. Also, I&apos;m assuming that you&apos;re actually using a PersistenceMapper component that persists to a relational database. If you&apos;re using the PersistenceMapperXML component then the rest of this article doesn&apos;t apply to you. Sorry. 
&lt;P&gt;Here&apos;s the problem: Using my ECO application, I load a particular&amp;nbsp;Person object&amp;nbsp;from the database and start editing values. Meanwhile, Damien who&apos;s also running the same application, loads up the same Person object. Given that I have not yet persisted my changes to the database, when Damien loads his instance, he gets the data from the database. He then changes the Firstname property. I persist my changes to the database, and all is fine. However, at some point Damien is going to try and persist his changes to the database. Should his changes overwrite mine? Should his attempt to persist the changes fail? What if I didn&apos;t change the Firstname attribute? Should it still&amp;nbsp;fail?&lt;/P&gt;What happens when he does try and persist his changes depends on how you, the developer of this app,&amp;nbsp;have configured optimistic locking. 
&lt;P&gt;First, let&apos;s look at where you setup optimistic locking, then we&apos;ll look at what the different options mean. Firstly, you need to turn optimistic locking on. Bring up your ECOSpace, click on an empty area of the designer so that the Object Inspector shows the properties of the ECOSpace. In the ECO | Persistence section, you should see a boolean property called OptimisticLocking. Set this to True. 
&lt;P&gt;But that&apos;s not all. You need to specify the type of optimistic locking you want to occur for each class in your system. Bring up one of your class diagrams, select a class (make sure it&apos;s the class you have selected, and not one of its attributes or methods) and look in the Object Inspector. Once you&apos;ve expanded the Eco sub-property, you should see a property called OptimisticLocking. The default value of this is, funnily enough, Default, but you can also choose Off, ModifiedMembers, AllMembers or Timestamp. In the rest of this article we&apos;ll be looking at what happens when Damien tries to persist his changes to the Person object, depending on which of these&amp;nbsp;values you&apos;ve selected. 
&lt;P&gt;&lt;IMG alt=&quot;&quot; hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/05/19/20040517001.gif&quot; align=baseline border=0&gt; 
&lt;P&gt;&lt;STRONG&gt;OptimisticLocking set to Off&lt;/STRONG&gt; 
&lt;P&gt;Setting OptimisticLocking to Off on your class means that no checks are performed before this object is persisted. So, when Damien persists his changes, the following SQL is executed: 
&lt;P&gt;&lt;FONT face=Courier size=1&gt;update Person &lt;BR&gt;set Firstname = &apos;Barney&apos; &lt;BR&gt;where BOLD_ID = 3&lt;/FONT&gt; 
&lt;P&gt;Not surprisingly, this will overwrite any changes I may have made to the Firstname attribute for this Person. Maybe that&apos;s what you want? Certainly it will execute faster than some of the other setting I&apos;ll mention shortly :-)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;OptimisticLocking set to Default&lt;/STRONG&gt; 
&lt;P&gt;Default basically means that the OptimisticLocking behaviour is determined by this class&apos; ancestor. So, if Person descended from some other class, say a Contact class, then how Damien&apos;s Person class behaved in this situation depends on the value of Contact&apos;s OptimisticLocking property.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;OptimisticLocking set to ModifiedMembers&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;As the name might suggest, this value will mean that before ECO persists the Person object, it will check to see if any of the attributes that have been changed on the class, have also been changed in the database. What this means, in the case of our Person object where Damien edited the Firstname property, is that the following SQL will be executed first:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Courier size=1&gt;SELECT B.BOLD_ID, B.BOLD_TYPE, B.Firstname &lt;BR&gt;FROM Person B &lt;BR&gt;WHERE B.BOLD_ID = 3&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;ECO&amp;nbsp;will then check to see if the returned value for Firstname is the same as the value in the class before Damien edited it. If its the same, then ECO assumes that this field has not been changed in the database, and proceeds to execute this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Courier size=1&gt;UPDATE Person &lt;BR&gt;SET Firstname =&amp;nbsp;&apos;Barney&apos; &lt;BR&gt;WHERE BOLD_ID = 3&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;However, if after executing the select, it finds that the value returned is different from the Firstname field prior to Damien&apos;s changes, it throws a&amp;nbsp;Borland.Eco.Internal.BoldSystem.EBoldOperationFailedForObjectList exception with the message &quot;Optimistic locking failed for 1 objects&quot;.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;OptimisticLocking set to AllMembers&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Hopefully by now you can guess this one. Like the previous example, ECO will check the database to see if the values are the same as when this Person object was first loaded, but this time it will check all attributes on the class, not just those that have been changed. So, in our example it will first execute SQL like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Courier size=1&gt;SELECT B.BOLD_ID, B.BOLD_TYPE, B.Firstname, B.Lastname &lt;BR&gt;FROM Person B WHERE B.BOLD_ID =&amp;nbsp;3&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If all fields have the same value as the attributes of our Person did prior to Damien&apos;s changes, it will then execute the following SQL:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Courier size=1&gt;UPDATE Person &lt;BR&gt;SET Firstname = &apos;Barney&apos;&lt;BR&gt;WHERE BOLD_ID = 3&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Note that it still only updates the fields that Damien changed, even though it first checks all fields.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Pitstop&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So far I don&apos;t think any of these have been very difficult to grasp. One way to look at them is that each setting gradually increases the requirements that must be satisfied in order for an object to be persisted successfully.&lt;/P&gt;
&lt;P&gt;We started with no requirements (OptimisticLocking = Off), then we went to the requirement that any attributes that are changed must not have been changed by anyone else (OptimisticLocking = ModifiedMembers). We then&amp;nbsp;stepped up a level again, requiring that none of the attributes of the class can have changed (OptimisticLocking = AllMembers). Well the last setting (OptimisticLocking = Timestamp) increases the strictness of these requirements another level again, but does it in a slightly different way.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;OptimisticLocking set to Timestamp&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you set OptimisticLocking to Timestamp on one or more of you classes, you&apos;ll need to go out to your PersistenceMapper component (in your ECOSpace) and change the SqlDatabaseConfig.UseTimestamp property to True (see the picture below if that doesn&apos;t make sense). You&apos;ll also need to invoke the Evolve Database function so that ECO can create you a new table called ECO_TIMESTAMP. This table contains a single field called BOLD_TIME_STAMP, which despite its name, is an Int field (at least in the SQLServer example I&apos;m playing with here).&lt;/P&gt;
&lt;P&gt;&lt;IMG alt=&quot;&quot; hspace=0 src=&quot;http://www.malcolmgroves.com/images/2004/05/19/20040517002.gif&quot; align=baseline border=0&gt;&lt;/P&gt;
&lt;P&gt;So, sticking with the same Person object example above, if we have OptimisticLocking set to Timestamp, here&apos;s what happens when Damien tries to persist his Person object:&lt;/P&gt;
&lt;P&gt;First, ECO will execute the following SQL:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Courier size=1&gt;UPDATE ECO_TIMESTAMP SET BOLD_TIME_STAMP = BOLD_TIME_STAMP + 1&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;This does two things. It increments the Timestamp field, and also returns the current value. ECO can then check that this value has not changed since this objects&apos; fields were loaded from the database. If this value is the same, ECO will then execute this SQL to persist the object: 
&lt;P&gt;&lt;FONT face=Courier size=1&gt;UPDATE Person SET Firstname =&amp;nbsp;&apos;Barney&apos; WHERE BOLD_ID =&amp;nbsp;3&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If it finds the timestamp field has been changed since this object was loaded (ie. the value in the field is greater than the one stored with the object) it will, like the other OptimisticLocking settings, throw a Borland.Eco.Internal.BoldSystem.EBoldOperationFailedForObjectList exception with the message &quot;Optimistic locking failed for 1 objects&quot;.&lt;/P&gt;
&lt;P&gt;It should be noted that all classes that are set to use Timestamp as their locking type will share the Timestamp field. So if Person and Appointment are both Timestamp-locked classes, and both persist to the same database, saving an Appointment object has the potential to stop someone else saving their Person object. This is neither good nor bad, it&apos;s just how it works. Sometimes, given certain relationships between classes, this may be the exact behaviour you want. If not, use one of the other techniques.&lt;/P&gt;
&lt;P&gt;Now, obviously this is a very simplistic example, but hopefully it&apos;s given you a feel for how Optimistic Locking works. The ability to assign different locking settings to different classes opens up quite a bit of flexibility. Looking at how each setting works, you might notice that each gradually increases the potential scope that ECO will check before persisting an object: from nothing, to changed fields of an object, to all fields of an object, and finally, with Timestamp, to potentially other classes. And if you want even more control, in a future article we&apos;ll have a look at the concept of Regions.&lt;/P&gt;
&lt;P&gt;If you want to dig deeper, I would recommend you do what I did: Spend a little time in&amp;nbsp;SQL Profiler (or a similar SQL monitoring tool) and play with the various Locking settings and see what SQL is thrown. &lt;/P&gt;
&lt;P&gt;Update: &lt;A href=&quot;http://blogs.borland.com/krish/archive/2004/07/16/855.aspx&quot;&gt;Krishnan&lt;/A&gt; has some follow up comments, concerns, suggestions, and &lt;A href=&quot;http://blogs.borland.com/jonashogstrom/archive/2004/10/22/1645.aspx&quot;&gt;Jonas&lt;/A&gt; responds in turn, along with some corrections for my article above. See what I&apos;ve started?&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/05/30.html#a70</guid>
			<pubDate>Sun, 30 May 2004 04:10:55 GMT</pubDate>
			</item>
		<item>
			<title>Next ECO Articles cont&apos;d</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/05/19.html#a68</link>
			<description>&lt;P&gt;Ok, thanks for everyone who commented or emailed their requests. Here&apos;s the list I have so far (in no particular order):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Optimistic Locking (off being reviewed as we speak)&lt;/LI&gt;
&lt;LI&gt;ECO Variables&lt;/LI&gt;
&lt;LI&gt;Constraints&lt;/LI&gt;
&lt;LI&gt;ECO from code (this will possibly be a few articles)&lt;/LI&gt;
&lt;LI&gt;ASP.NET and ECO&lt;/LI&gt;
&lt;LI&gt;Bold&amp;nbsp;&amp;lt;-&amp;gt; ECO migration&lt;/LI&gt;
&lt;LI&gt;Optimisation (ie. lots of objects, lots of classes, lots of relations, what do I do?)&lt;/LI&gt;
&lt;LI&gt;Services&amp;nbsp;(ie. UndoServices, DirtyListServices, etc)&lt;/LI&gt;
&lt;LI&gt;Autoforms&lt;/LI&gt;
&lt;LI&gt;Legacy Databases&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Some of these I&apos;ll delay until the next release (not telling which of course :-P ). Don&apos;t be too harsh on me for that, the others will probably take me that long to write anyway, and trust me, some of them will benefit for waiting until then. Of course, keep telling me others and I&apos;ll keep updating the list. Also, feel free to jump in and write some of these yourself :-)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/05/19.html#a68</guid>
			<pubDate>Wed, 19 May 2004 05:41:42 GMT</pubDate>
			</item>
		<item>
			<title>Next ECO Articles</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/05/14.html#a67</link>
			<description>&lt;P&gt;I&apos;ve got an article mostly done on Optimistic Locking in ECO, and have the examples for one on ECO Variables, but just wondering what else people are interested in me covering here? I&apos;m not really interested&amp;nbsp;in duplicating the tutorials that are already up on the Borland site,&amp;nbsp;but feel free to leave a comment telling me what topics you&apos;d like to see. Speak up, or you&apos;ll just have to put up with me covering whatever takes my fancy.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/05/14.html#a67</guid>
			<pubDate>Fri, 14 May 2004 05:28:12 GMT</pubDate>
			</item>
		<item>
			<title>Association Classes</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/05/13.html#a65</link>
			<description>&lt;P&gt;OK, one more topic to go and then we&apos;ll leave the modelling surface in ECO for awhile&amp;nbsp;to look at other areas.&amp;nbsp;Today&apos;s topic is Association classes. (BTW. I&apos;ve borrowed the idea for this example from the MeetingManager example that ships with Delphi, but the implementation varies a little bit.) &lt;/P&gt;
&lt;P&gt;Let&apos;s forget ECO for a second and talk about why we might want Association classes in general. &lt;/P&gt;
&lt;P&gt;Think of the model we looked at in the Derived Association example last time. Here it is again to jog your memory.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/30/20040430002.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;We have a Person class and an Appointment class, and a relationship between them. The Appointment class has attributes for Start, Duration and one for whether or not it is confirmed. It&apos;s this Confirmed attribute I want to focus on. &lt;/P&gt;
&lt;P&gt;There is an argument&amp;nbsp; that the Confirmed attribute does not belong on the Appointment class because you don&apos;t actually confirm an appointment, only whether you will attend the appointment. This problem is highlighted if you consider the case of a meeeting with multiple attendees. You need to allow for the fact that some people will attend and some won&apos;t. (Note: The example in this tutorial doesn&apos;t support multiple Person&apos;s per appointment, but it would be reasonable to expect this to occur in a real world application). So where does the Confirmed attribute belong &amp;nbsp;if not on the Appointment ? I&apos;m pretty sure it doesn&apos;t belong on the Person class. The argument goes that Confirmed is actually an attribute of the relationship between the Person and the Appointment. Put another way, you do not confirm an Appointment, you confirm a Person&apos;s&amp;nbsp;participation in an Appointment.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Let&apos;s think of another example. The example that was used to explain this concept to me was employment. If you have a Person class and a Company class, and a relationship between them that indicates employment, where would you put the Start Date of the employment. You wouldn&apos;t put it on the Person (what if they have multiple jobs) and you wouldn&apos;t put it on the Company (what if they have multiple employees). StartDate is really an attribute of the employment itself, which in this case is an association between the two classes. &lt;/P&gt;
&lt;P&gt;You may not agree with either of these examples, and there are certainly other ways you can model them. That&apos;s OK. Like most things in software development, there is usually no one right way of doing anything. But Association classes are&amp;nbsp;a perfectly valid modelling construct to use, and can be extremely powerful&amp;nbsp;(more about that further down). Try using them for awhile. Dismissing something from a position of authority is fine, dismissing something from any other position is kinda scary. &lt;/P&gt;
&lt;P&gt;So, how do we create an attribute on an association? Well, perhaps not surprisingly, we use an Association class. We create a class and relate it to our association. Any attributes we want to add to the association, we add to our Association class instead. Let&apos;s look at how we might model the changes to our Appointment we discussed above.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511001.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;I&apos;ve removed the Derived Relationship for now, but we&apos;ll add it back later. You can see I&apos;ve removed the Confirmed attribute from our Appointment, and added another class called Participancy which contains our Confirmed attribute. this Participancy class is going to be our Association class.&amp;nbsp;An Association class is&amp;nbsp;just a standard ECO class,&amp;nbsp;you don&apos;t do anything special when creating the class to make it an&amp;nbsp;Association class. Just&amp;nbsp;select the association between the two classes and enter the name of the Association class, in this case Participancy, into the AssociationClass attribute. Just to make it stand out, I&apos;ve also change the foreground colour of my participancy class. &lt;/P&gt;
&lt;P&gt;So, that was pretty easy, but what does it all mean? In the diagram below, I&apos;ve tried to show what the above arrangement looks like in sourcecode. Note, I&apos;ve built this diagram manually, purely to try and explain what is going on. Don&apos;t go looking for a picture like this in the IDE.&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511007.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;As you can see, we still have our association between Person and Appointments, and we can navigate that with absolutely no reference to our Association class. However, we also have a path between Person and Appointment that goes via our Association class. This effectively gives us two ways of navigating from Person to Appointment. One way we use the existing direct association, and the other way we go via the&amp;nbsp;Association class.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;From a Person object, we have an association to a collection of Participancy objects, one for each Appointment we have an association with. From an Appointment object, we have an association back to&amp;nbsp;a single Participany object. This makes sense as an Appointment is only associated with a single Person. &lt;/P&gt;
&lt;P&gt;So, I&apos;ll repeat, what does it all mean? Well, it means that I can navigate from my Person to my Appointment (or vice versa) a few ways. Starting at my Person object, I can still say self.Appointments which will return me a collection of Appointment objects, but I can also do this:&lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511002.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;Notice my context (in the caption bar) is still Person. As it says down the bottom,&amp;nbsp;self.Participancy will return me a collection of Participancy objects. Also note on the right hand side that each of these Participancy objects have the confirmed attribute, as well as an&amp;nbsp;Appointments collection and Owner. &lt;/P&gt;
&lt;P&gt;If we use that Appointments attribute of the Participancy object by using OCL like this: &lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511003.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;We are now getting back a collection of Appointment objects, with the correct looking attributes (but note, as I mentioned before, our Appointment class now has a Participancy attribute as well). &lt;/P&gt;
&lt;P&gt;Using OCL like this: &lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511004.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;We are now getting back a collection of Participancy objects, but only those where the Confirmed attribute is True. And to complete the set, if we use OCL like this: &lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511005.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;We are getting back a collection of all Appointments for this Person that are confirmed. Of course, you can access things in a similar way from C# or Delphi&amp;nbsp;code, as the attributes are there in code, there&apos;s no black magic going on (We&apos;ll look at accessing ECO from code in much more detail in a later article) &lt;/P&gt;
&lt;P&gt;So,hopefully that gives you some feeling for accessing the attributes of an Association class. But my model is still broken, I need to put back the derived relationship from last week, but this time using our Association class. this is pretty easy now, as the last lot of OCL I showed is exactly the OCL I need. So, like last week, create your one way association between Person and Appointment, set it as Derived and Transient, and enter the OCL shown below in the DerivationOCL property &lt;/P&gt;
&lt;P&gt;&lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/05/11/20040511006.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;Now, our model is restored and our ConfirmedAppointments derived relationship&amp;nbsp;should work as before. However, by using our Association class, we have hopefully more correctly modelled the true nature of our system. In addition, hopefully you realise that our Participancy class, while an Association class, is still just a class, so it can have attributes, methods and even associations with other classes. Think about that last one for awhile and you might start to see some interesting applications for Association classes. &lt;/P&gt;
&lt;P&gt;Like I said before, a lot of times this comes down to personal taste. I&apos;m very happy to argue the relative merits of Association classes, but only if we can do it over a drink :-)&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/05/13.html#a65</guid>
			<pubDate>Thu, 13 May 2004 02:56:38 GMT</pubDate>
			</item>
		<item>
			<title>Derived Associations</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/04/30.html#a60</link>
			<description>&lt;P&gt;OK, we&apos;ve spent the last few days in the model, talking about Packages, and all sorts of Derived Attributes. I want to spend a bit more time in this area, specifically on Derived Associations and Association Classes, then we&apos;ll head off to other areas such as&amp;nbsp;Persistence and Optimistic Locking, before starting to look at UI stuff. Feel free to let me know other areas you&apos;d like to see covered.&lt;/P&gt;
&lt;P&gt;OK, let&apos;s look at Derived Associations. I&apos;m assuming you&apos;ve worked through the &lt;A href=&quot;http://www.borland.com/delphi_net/architect/eco/tutorial/&quot;&gt;ECO Tutorial&lt;/A&gt; on &lt;A href=&quot;http://www.borland.com/delphi_net/architect/eco/tutorial/tutorial2.html&quot;&gt;Associations&lt;/A&gt;, or at the very least have created a few associations in ECO before. I&amp;nbsp;won&apos;t be covering the same territory here. If you&apos;re not comfortable creating associations and what all the bits like Multiplicity mean, then&amp;nbsp;off you go, this&apos;ll still be here when you get back.&lt;/P&gt;
&lt;P&gt;Look at the model below. I&apos;m trying to stick with the same type of problem domain for a few articles, so this is still in the realm of Appointments (albeit cleaned up a little, just to keep it simple).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/30/20040430001.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;We have a Person class and an Appointment class, with an association between them where an Appointment can belong to only one Person, and a Person can have zero to many Appointments. Note however, that the Appointment has a Confirmed attribute. You may decide that you need to deal with only confirmed appointments so often, that you want&amp;nbsp;another association between these two classes that only displays appointments that have the Confirmed attribute set. &lt;/P&gt;
&lt;P&gt;However, this isn&apos;t really&amp;nbsp;a new association, as it&amp;nbsp;should be&amp;nbsp;possible to calculate the collection of confirmed appointments from our existing association. If you&apos;re thinking that kinda sounds like Derived Attributes, you&apos;d be right. We can define a new association, that doesn&apos;t get persisted to the database, but exists in our model. We use OCL to derive the collection of Appointments we want to appear as part of this association.&lt;/P&gt;
&lt;P&gt;So, in the model below, I&apos;ve added a new association between the two classes. You define the association pretty much the same way you define any association. However, note I&apos;ve set it to be a one way association (by setting the Navigable property on the Appointment end (End2) to False). This association is for navigating from the Person down to the Appointment. In this scenario we can still use our existing association to get from the Appointment back up to the Person. Whether an Appointment is confirmed or not does not change the Person who owns it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/30/20040430002.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;Note I&apos;ve also set the derived property to True, and the Persistence property to Transient. Lastly I&apos;ve specified some OCL in the DerivationOCL property. This is the OCL that is going to determine which Appointment objects appear as part of this association:&lt;/P&gt;
&lt;P&gt;Appointments-&amp;gt;select(Confirmed)&lt;/P&gt;
&lt;P&gt;This is basically saying, from all Appointments associated with this Person, select the subset where the Confirmed attribute is True. &lt;/P&gt;
&lt;P&gt;The screen shot below shows the two associations at runtime. Person.Appointments shows all appointments for a specific person (the second grid from the top), while Person.ConfirmedAppointments (the bottom grid) shows only those appointments for a specific Person that have the Confirmed attribute set to True.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/30/20040430003.gif&quot;&gt;&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/04/30.html#a60</guid>
			<pubDate>Fri, 30 Apr 2004 01:36:28 GMT</pubDate>
			</item>
		<item>
			<title>Derived Attributes Part 3 - Reverse Derived Attributes</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/04/29.html#a58</link>
			<description>&lt;P&gt;If you take a look at sourcecode for the Finish derived attribute declaration from the previous model, you&apos;ll note it looks like this:&lt;/P&gt;
&lt;P&gt;property Finish: DateTime read get_Finish;&lt;/P&gt;
&lt;P&gt;i.e. it is a read-only property. This kinda makes sense, given what we now know about derived attributes. If the value of my attribute is calculated, the framework by itself cannot figure out how to undo it i.e. how to tear apart the value into the original parts used to calculate it in the first place. This may not even be algorithmically possible. &lt;/P&gt;
&lt;P&gt;However, sometimes it is possible, and in these cases, we need a way to&amp;nbsp;tell the framework how to do it. Let&apos;s stick with our Appointment example. The Finish time was derived by taking the Start time and adding the number of minutes held in the Duration attribute. In my case, if someone assigns a new value to the Finish attribute, I&apos;ll change the Duration to reflect the difference between my Start time and this new Finish value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/29/20040429002.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;How? Well, select the Finish attribute in your model, and in the object inspector, set the DerivedSettable property to True. If you now look at the sourcecode for the Finish declaration, a setter method (called set_Finish)&amp;nbsp;has been added. We&apos;ll add our logic to recalculate the Duration in this setter method, but first we need to tell ECO that we are changing the logic in here, and to leave it alone in the future. We do this by removing the [ECOAutoMaintained] attribute from the property declaration in our sourcecode (Don&apos;t worry, there is a comment reminding you to do this in the generated setter method). My new set_Finish method looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot;&gt;procedure Appointment.set_Finish(Value: DateTime);&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; &lt;a href=&quot;//&quot;&gt;//&lt;/a&gt; If you add user code here, please remove the [EcoAutoMaintained] attribute&lt;BR&gt;&amp;nbsp; &lt;a href=&quot;//&quot;&gt;//&lt;/a&gt; from the property declaration in the interface section&lt;BR&gt;&amp;nbsp; Duration := Convert.ToInt32(Value.Subtract(Start).TotalMinutes);&lt;BR&gt;end;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The new value for Finish is passed in as the Value parameter. I subtract from this the Start time, and use the&amp;nbsp;the difference in minutes to set the value of the Duration attribute.&lt;/P&gt;
&lt;P&gt;What this means is that not only can I set the Start and Duration and it will calculate the Finish, but I can set the Finish and it will calculate a new Duration.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/04/29.html#a58</guid>
			<pubDate>Thu, 29 Apr 2004 04:17:09 GMT</pubDate>
			</item>
		<item>
			<title>Derived Attributes Part 2 - Code Derived Attributes</title>
			<link>http://www.malcolmgroves.com/categories/eco/2004/04/29.html#a57</link>
			<description>&lt;P&gt;Ok, so yesterday we looked at adding attributes to our ECO classes where the value of those attributes was calculated at runtime using OCL. If you haven&apos;t already, look through the link I gave yesterday to &lt;A href=&quot;http://www.viewpointsa.com/bold_resources/getting_started_with_bold/Part3-OCL.html&quot;&gt;Anthony Richardson&apos;s OCL Tutorial&lt;/A&gt;, as it is possible to embed some fairly rich logic into your model using this language.&lt;/P&gt;
&lt;P&gt;That said, lets not kid ourselves. Delphi and C# are much richer languages than OCL, so there will come a time where either it&apos;s not possible to calculate your attribute&apos;s value using OCL, or where you are more comfortable doing it in code. So, let&apos;s look at Code Derived Attributes.&lt;/P&gt;
&lt;P&gt;I&apos;ve created a new class called Appointment, which has a Start attribute of type System.DateTime, which&amp;nbsp;represents the start time of the Appointment&amp;nbsp;and a Duration attribute of type Integer, which is the length&amp;nbsp;of the Appointment in minutes. I&apos;ve also then created a Derived Attribute called Finish, also of type System.DateTime. Just like yesterday, I&apos;ve set its Derived property to True and its Persistence property to Transient. However, unlike yesterday, I have not specified any OCL to calculate the value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;IMG src=&quot;http://www.malcolmgroves.com/images/2004/04/29/20040429001.gif&quot;&gt;&lt;/P&gt;
&lt;P&gt;When the ECO framework finds a derived attribute that has no OCL, it goes looking for a method,&amp;nbsp;using reflection, of a particular signature and name, specifically:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot;&gt;function &amp;lt;Attribute Name&amp;gt;DeriveAndSubscribe(reevaluateSubscriber,&amp;nbsp;resubscribeSubscriber: ISubscriber): system.object;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In this case, my attribute is called Finish, so it looks for a method called:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot;&gt;function FinishDeriveAndSubscribe(reevaluateSubscriber,&amp;nbsp;resubscribeSubscriber: ISubscriber): system.object;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If it finds this method, it executes it, and uses the return value as the attribute&apos;s value. So its your job inside this method to do whatever you need to calculate the attribute&apos;s value. In my case, I want to add the Duration in minutes to my Start time, so my method looks like this:&lt;/P&gt;
&lt;P&gt;&lt;FONT face=&quot;Courier, Monospace&quot;&gt;function Appointment.FinishDeriveAndSubscribe(reevaluateSubscriber,&amp;nbsp;resubscribeSubscriber: ISubscriber): system.object;&lt;BR&gt;begin&lt;BR&gt;&amp;nbsp; AsIObject.Properties[&apos;Start&apos;].SubscribeToValue(reevaluateSubscriber);&lt;BR&gt;&amp;nbsp; AsIObject.Properties[&apos;Duration&apos;].SubscribeToValue(reevaluateSubscriber);&lt;BR&gt;&amp;nbsp; result := Start.AddMinutes(Duration);&lt;BR&gt;end;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Now hang on a sec, the last line makes sense, but what are the first two lines doing? &lt;/P&gt;
&lt;P&gt;Well, let&apos;s step back a bit. ECO does not actually derive the value of your attribute every time someone asks for it. Instead it caches the value of the attribute after it is first calculated, and returns this cached value on subsequent requests, provided the attrbiute is not marked as out of date. How would our attribute get marked as out of date?&amp;nbsp; Well, that&apos;s where the first two lines of code above come in. We&apos;ve subscribed to be notified whenever Start or Duration are changed. When we are notified, the ECO framework will flag our Finish attribute as out of date. Then, when the next request for its value is made, before the cached value is returned this flag will be checked and, the value of the atribute will be recalculated.&lt;/P&gt;
&lt;P&gt;Subscriptions in ECO are an important&amp;nbsp;topic that I plan to cover in&amp;nbsp;future posts, but in the meantime, make sure you subscribe to any other attributes on which you are depending.&lt;/P&gt;
&lt;P&gt;Not quite as easy as using OCL, but way more powerful, as you now have full access to the entire .NET Framework to use in calculating your attribute&apos;s value.&lt;/P&gt;</description>
			<guid>http://www.malcolmgroves.com/categories/eco/2004/04/29.html#a57</guid>
			<pubDate>Thu, 29 Apr 2004 03:43:57 GMT</pubDate>
			</item>
		</channel>
	</rss>
