<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <link rel="stylesheet" type="text/css" href="docs.css"> <!--[if gte IE 5]> <link href="docs_ie.css" rel="stylesheet" type="text/css"> <![endif]--> </head> <body><div id="pagecontainer"><table><tr><td width="5"> </td><td><a name="Structured"></a><br> <a name="outline161"></a><br><h1>5. Structured objects</h1><br> It's time to extend our business domain with another class and see how db4o handles object interrelations. Let's give our pilot a vehicle.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>namespace Db4odoc.Tutorial.F1.Chapter2<br> {<br> public class Car<br> {<br> string _model;<br> Pilot _pilot;<br> <br> public Car(string model)<br> {<br> _model = model;<br> _pilot = null;<br> }<br> <br> public Pilot Pilot<br> {<br> get<br> {<br> return _pilot;<br> }<br> <br> set<br> {<br> _pilot = value;<br> }<br> }<br> <br> public string Model <br> {<br> get<br> {<br> return _model;<br> }<br> }<br> <br> override public string ToString()<br> {<br> return string.Format("{0}[{1}]", _model, _pilot);<br> }<br> }<br> }<br> </code></td></tr></table> <br> <br> <ul> <a name="outline162"></a><br><h2>5.1. Storing structured objects</h2><br> To store a car with its pilot, we just call #Store() on our top level object, the car. The pilot will be stored implicitly.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// storeFirstCar<br> Car car1 = new Car("Ferrari");<br> Pilot pilot1 = new Pilot("Michael Schumacher", 100);<br> car1.Pilot = pilot1;<br> db.Store(car1);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "storeFirstCar")' /></td></tr></table> <br> <br> Of course, we need some competition here. This time we explicitly store the pilot before entering the car - this makes no difference.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// storeSecondCar<br> Pilot pilot2 = new Pilot("Rubens Barrichello", 99);<br> db.Store(pilot2);<br> Car car2 = new Car("BMW");<br> car2.Pilot = pilot2;<br> db.Store(car2);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "storeSecondCar")' /></td></tr></table> <br> <br> <a name="outline163"></a><br><h2>5.2. Retrieving structured objects</h2><br> <ul> <a name="outline164"></a><br><h2>5.2.1. QBE</h2><br> To retrieve all cars, we simply provide a 'blank' prototype.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveAllCarsQBE<br> Car proto = new Car(null);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveAllCarsQBE")' /></td></tr></table> <br> <br> We can also query for all pilots, of course.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveAllPilotsQBE<br> Pilot proto = new Pilot(null, 0);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveAllPilotsQBE")' /></td></tr></table> <br> <br> Now let's initialize our prototype to specify all cars driven by Rubens Barrichello.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveCarByPilotQBE<br> Pilot pilotproto = new Pilot("Rubens Barrichello", 0);<br> Car carproto = new Car(null);<br> carproto.Pilot = pilotproto;<br> IObjectSet result = db.QueryByExample(carproto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveCarByPilotQBE")' /></td></tr></table> <br> <br> What about retrieving a pilot by car? We simply don't need that - if we already know the car, we can simply access the pilot field directly.<br> <br> <a name="outline165"></a><br><h2>5.2.2. Native Queries</h2><br> Using native queries with constraints on deep structured objects is straightforward, you can do it just like you would in plain other code. <br> <br> Let's constrain our query to only those cars driven by a Pilot with a specific name:<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>public class RetrieveCarsByPilotNamePredicate : Predicate<br> {<br> readonly string _pilotName;<br> public RetrieveCarsByPilotNamePredicate(string pilotName)<br> {<br> _pilotName = pilotName;<br> }<br> public bool Match(Car candidate)<br> {<br> return candidate.Pilot.Name == _pilotName;<br> }<br> }</code></td></tr></table> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveCarsByPilotNameNative<br> string pilotName = "Rubens Barrichello";<br> IObjectSet results = db.Query(new RetrieveCarsByPilotNamePredicate(pilotName));<br> ListResult(results);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveCarsByPilotNameNative")' /></td></tr></table> <br> <br> Using generics syntax this is a lot simpler:<br> <br> <b>C# Generics</b><br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveCarsByPilotNameNative<br> string pilotName = "Rubens Barrichello";<br> List<Car> results = db.Query<Car>(delegate(Car car) {<br> return car.Pilot.Name == pilotName; });<br> listResults(results);</code></td></tr></table> <br> <br> <br> <a name="outline166"></a><br><h2>5.2.3. SODA Query API</h2><br> In order to use SODA for querying for a car given its pilot's name we have to descend two levels into our query.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveCarByPilotNameQuery<br> IQuery query = db.Query();<br> query.Constrain(typeof(Car));<br> query.Descend("_pilot").Descend("_name")<br> .Constrain("Rubens Barrichello");<br> IObjectSet result = query.Execute();<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveCarByPilotNameQuery")' /></td></tr></table> <br> <br> We can also constrain the pilot field with a prototype to achieve the same result.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveCarByPilotProtoQuery<br> IQuery query = db.Query();<br> query.Constrain(typeof(Car));<br> Pilot proto = new Pilot("Rubens Barrichello", 0);<br> query.Descend("_pilot").Constrain(proto);<br> IObjectSet result = query.Execute();<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveCarByPilotProtoQuery")' /></td></tr></table> <br> <br> We have seen that descending into a query provides us with another query. Starting out from a query root we can descend in multiple directions. In practice this is the same as ascending from one child to a parent and descending to another child. We can conclude that queries turn one-directional references in our objects into true relations. Here is an example that queries for "a Pilot that is being referenced by a Car, where the Car model is 'Ferrari'":<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrievePilotByCarModelQuery<br> IQuery carQuery = db.Query();<br> carQuery.Constrain(typeof(Car));<br> carQuery.Descend("_model").Constrain("Ferrari");<br> IQuery pilotQuery = carQuery.Descend("_pilot");<br> IObjectSet result = pilotQuery.Execute();<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrievePilotByCarModelQuery")' /></td></tr></table> <br> <br> <img border="0" src="querygraph/3net.gif" /><br> <br> <br> </ul> <a name="outline167"></a><br><h2>5.3. Updating structured objects</h2><br> To update structured objects in db4o, we simply call #Store() on them again.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updateCar<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot = new Pilot("Somebody else", 0);<br> db.Store(found);<br> result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updateCar")' /></td></tr></table> <br> <br> Let's modify the pilot, too.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updatePilotSingleSession<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);<br> result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updatePilotSingleSession")' /></td></tr></table> <br> <br> Nice and easy, isn't it? But wait, there's something evil lurking right behind the corner. Let's see what happens if we split this task in two separate db4o sessions: In the first we modify our pilot and update his car:<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updatePilotSeparateSessionsPart1<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updatePilotSeparateSessionsPart1")' /></td></tr></table> <br> <br> And in the second, we'll double-check our modification:<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updatePilotSeparateSessionsPart2<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updatePilotSeparateSessionsPart2")' /></td></tr></table> <br> <br> Looks like we're in trouble: Why did the Pilot's points not change? What's happening here and what can we do to fix it?<br> <br> <ul> <a name="outline168"></a><br><h2>5.3.1. Update depth</h2><br> Imagine a complex object with many members that have many members themselves. When updating this object, db4o would have to update all its children, grandchildren, etc. This poses a severe performance penalty and will not be necessary in most cases - sometimes, however, it will.<br> <br> So, in our previous update example, we were modifying the Pilot child of a Car object. When we saved the change, we told db4o to save our Car object and assumed that the modified Pilot would be updated. But we were modifying and saving in the same manner as we were in the first update sample, so why did it work before? The first time we made the modification, db4o never actually had to retrieve the modified Pilot it returned the same one that was still in memory that we modified, but it never actually updated the database. The fact that we saw the modified value was, in fact, a bug. Restarting the application would show that the value was unchanged.<br> <br> To be able to handle this dilemma as flexible as possible, db4o introduces the concept of update depth to control how deep an object's member tree will be traversed on update. The default update depth for all objects is 1, meaning that only primitive and String members will be updated, but changes in object members will not be reflected.<br> <br> db4o provides means to control update depth with very fine granularity. For our current problem we'll advise db4o to update the full graph for Car objects by setting #CascadeOnUpdate() for this class accordingly.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updatePilotSeparateSessionsImprovedPart1<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);<br> }</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updatePilotSeparateSessionsImprovedPart1")' /></td></tr></table> <br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// updatePilotSeparateSessionsImprovedPart2<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "updatePilotSeparateSessionsImprovedPart2")' /></td></tr></table> <br> <br> This looks much better.<br> <br> Note that container configuration must be passed when the container is opened.<br> <br> We'll cover update depth as well as other issues with complex object graphs and the respective db4o configuration options in more detail in a later chapter.<br> <br> </ul> <a name="outline169"></a><br><h2>5.4. Deleting structured objects</h2><br> As we have already seen, we call #Delete() on objects to get rid of them.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// deleteFlat<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> db.Delete(found);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "deleteFlat")' /></td></tr></table> <br> <br> Fine, the car is gone. What about the pilots?<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveAllPilotsQBE<br> Pilot proto = new Pilot(null, 0);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveAllPilotsQBE")' /></td></tr></table> <br> <br> Ok, this is no real surprise - we don't expect a pilot to vanish when his car is disposed of in real life, too. But what if we want an object's children to be thrown away on deletion, too?<br> <br> <ul> <a name="outline170"></a><br><h2>5.4.1. Recursive deletion</h2><br> You may already suspect that the problem of recursive deletion (and perhaps its solution, too) is quite similar to our little update problem, and you're right. Let's configure db4o to delete a car's pilot, too, when the car is deleted.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// deleteDeep<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName)){<br> IObjectSet result = db.QueryByExample(new Car("BMW"));<br> Car found = (Car)result.Next();<br> db.Delete(found);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);<br> }</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "deleteDeep")' /></td></tr></table> <br> <br> Again: Note that configuration should be passed to the call opening ObjectContainer.<br> <br> Let's have a look at our pilots again.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveAllPilots<br> Pilot proto = new Pilot(null, 0);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveAllPilots")' /></td></tr></table> <br> <br> <a name="outline171"></a><br><h2>5.4.2. Recursive deletion revisited</h2><br> But wait - what happens if the children of a removed object are still referenced by other objects?<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// deleteDeepRevisited<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))<br> {<br> IObjectSet result = db.QueryByExample(new Pilot("Michael Schumacher", 0));<br> Pilot pilot = (Pilot)result.Next();<br> Car car1 = new Car("Ferrari");<br> Car car2 = new Car("BMW");<br> car1.Pilot = pilot;<br> car2.Pilot = pilot;<br> db.Store(car1);<br> db.Store(car2);<br> db.Delete(car2);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);<br> }</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "deleteDeepRevisited")' /></td></tr></table> <br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// retrieveAllPilots<br> Pilot proto = new Pilot(null, 0);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.chapter2.StructuredExample", "retrieveAllPilots")' /></td></tr></table> <br> <br> Houston, we have a problem - and there's no simple solution at hand. Currently db4o does <b>not</b> check whether objects to be deleted are referenced anywhere else, so please be very careful when using this feature.<br> <br> Let's clear our database for the next chapter.<br> <br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>// deleteAll<br> IObjectSet result = db.QueryByExample(typeof(Object));<br> foreach (object item in result)<br> {<br> db.Delete(item);<br> }</code></td><td class="lg" align="left" valign="bottom" width=43><input type='button' class='button' value='Run' onclick='window.external.RunExample("com.db4odoc.f1.Util", "deleteAll")' /></td></tr></table> <br> <br> </ul> <a name="outline172"></a><br><h2>5.5. Conclusion</h2><br> So much for object associations: We can hook into a root object and climb down its reference graph to specify queries. But what about multi-valued objects like arrays and collections? We will cover this in the <a href="Collections.html#Collections">next chapter</a> .<br> <br> <a name="outline173"></a><br><h2>5.6. Full source</h2><br> <table width="100%" cellpadding="3" cellspacing="0" border="0"><tr><td class="lg"> <code>using System;<br> using System.IO;<br> using Db4objects.Db4o;<br> using Db4objects.Db4o.Config;<br> using Db4objects.Db4o.Query;<br> namespace Db4odoc.Tutorial.F1.Chapter2<br> {<br> public class StructuredExample : Util<br> {<br> readonly static string YapFileName = Path.Combine(<br> Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),<br> "formula1.yap"); <br> <br> public static void Main(String[] args)<br> {<br> File.Delete(YapFileName);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName))<br> {<br> StoreFirstCar(db);<br> StoreSecondCar(db);<br> RetrieveAllCarsQBE(db);<br> RetrieveAllPilotsQBE(db);<br> RetrieveCarByPilotQBE(db);<br> RetrieveCarByPilotNameQuery(db);<br> RetrieveCarByPilotProtoQuery(db);<br> RetrievePilotByCarModelQuery(db);<br> UpdateCar(db);<br> UpdatePilotSingleSession(db);<br> UpdatePilotSeparateSessionsPart1(db);<br> }<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName))<br> {<br> UpdatePilotSeparateSessionsPart2(db);<br> }<br> UpdatePilotSeparateSessionsImprovedPart1();<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(YapFileName))<br> {<br> UpdatePilotSeparateSessionsImprovedPart2(db);<br> DeleteFlat(db);<br> }<br> DeleteDeep();<br> DeleteDeepRevisited();<br> }<br> public static void StoreFirstCar(IObjectContainer db)<br> {<br> Car car1 = new Car("Ferrari");<br> Pilot pilot1 = new Pilot("Michael Schumacher", 100);<br> car1.Pilot = pilot1;<br> db.Store(car1);<br> }<br> public static void StoreSecondCar(IObjectContainer db)<br> {<br> Pilot pilot2 = new Pilot("Rubens Barrichello", 99);<br> db.Store(pilot2);<br> Car car2 = new Car("BMW");<br> car2.Pilot = pilot2;<br> db.Store(car2);<br> }<br> public static void RetrieveAllCarsQBE(IObjectContainer db)<br> {<br> Car proto = new Car(null);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);<br> }<br> public static void RetrieveAllPilotsQBE(IObjectContainer db)<br> {<br> Pilot proto = new Pilot(null, 0);<br> IObjectSet result = db.QueryByExample(proto);<br> ListResult(result);<br> }<br> public static void RetrieveCarByPilotQBE(IObjectContainer db)<br> {<br> Pilot pilotproto = new Pilot("Rubens Barrichello", 0);<br> Car carproto = new Car(null);<br> carproto.Pilot = pilotproto;<br> IObjectSet result = db.QueryByExample(carproto);<br> ListResult(result);<br> }<br> public static void RetrieveCarByPilotNameQuery(IObjectContainer db)<br> {<br> IQuery query = db.Query();<br> query.Constrain(typeof(Car));<br> query.Descend("_pilot").Descend("_name")<br> .Constrain("Rubens Barrichello");<br> IObjectSet result = query.Execute();<br> ListResult(result);<br> }<br> public static void RetrieveCarByPilotProtoQuery(IObjectContainer db)<br> {<br> IQuery query = db.Query();<br> query.Constrain(typeof(Car));<br> Pilot proto = new Pilot("Rubens Barrichello", 0);<br> query.Descend("_pilot").Constrain(proto);<br> IObjectSet result = query.Execute();<br> ListResult(result);<br> }<br> public static void RetrievePilotByCarModelQuery(IObjectContainer db)<br> {<br> IQuery carQuery = db.Query();<br> carQuery.Constrain(typeof(Car));<br> carQuery.Descend("_model").Constrain("Ferrari");<br> IQuery pilotQuery = carQuery.Descend("_pilot");<br> IObjectSet result = pilotQuery.Execute();<br> ListResult(result);<br> }<br> public static void RetrieveAllPilots(IObjectContainer db)<br> {<br> IObjectSet results = db.QueryByExample(typeof(Pilot));<br> ListResult(results);<br> }<br> public static void RetrieveAllCars(IObjectContainer db)<br> {<br> IObjectSet results = db.QueryByExample(typeof(Car));<br> ListResult(results);<br> }<br> public class RetrieveCarsByPilotNamePredicate : Predicate<br> {<br> readonly string _pilotName;<br> public RetrieveCarsByPilotNamePredicate(string pilotName)<br> {<br> _pilotName = pilotName;<br> }<br> public bool Match(Car candidate)<br> {<br> return candidate.Pilot.Name == _pilotName;<br> }<br> }<br> public static void RetrieveCarsByPilotNameNative(IObjectContainer db)<br> {<br> string pilotName = "Rubens Barrichello";<br> IObjectSet results = db.Query(new RetrieveCarsByPilotNamePredicate(pilotName));<br> ListResult(results);<br> }<br> public static void UpdateCar(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot = new Pilot("Somebody else", 0);<br> db.Store(found);<br> result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);<br> }<br> public static void UpdatePilotSingleSession(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);<br> result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);<br> }<br> public static void UpdatePilotSeparateSessionsPart1(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);<br> }<br> public static void UpdatePilotSeparateSessionsPart2(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);<br> }<br> public static void UpdatePilotSeparateSessionsImprovedPart1()<br> {<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnUpdate(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> found.Pilot.AddPoints(1);<br> db.Store(found);<br> }<br> }<br> public static void UpdatePilotSeparateSessionsImprovedPart2(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> ListResult(result);<br> }<br> public static void DeleteFlat(IObjectContainer db)<br> {<br> IObjectSet result = db.QueryByExample(new Car("Ferrari"));<br> Car found = (Car)result.Next();<br> db.Delete(found);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);<br> }<br> public static void DeleteDeep()<br> {<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName)){<br> IObjectSet result = db.QueryByExample(new Car("BMW"));<br> Car found = (Car)result.Next();<br> db.Delete(found);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);<br> }<br> }<br> public static void DeleteDeepRevisited()<br> {<br> IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();<br> config.Common.ObjectClass(typeof(Car)).CascadeOnDelete(true);<br> using(IObjectContainer db = Db4oEmbedded.OpenFile(config, YapFileName))<br> {<br> IObjectSet result = db.QueryByExample(new Pilot("Michael Schumacher", 0));<br> Pilot pilot = (Pilot)result.Next();<br> Car car1 = new Car("Ferrari");<br> Car car2 = new Car("BMW");<br> car1.Pilot = pilot;<br> car2.Pilot = pilot;<br> db.Store(car1);<br> db.Store(car2);<br> db.Delete(car2);<br> result = db.QueryByExample(new Car(null));<br> ListResult(result);<br> }<br> }<br> }<br> }<br> </code></td></tr></table> <br> <br><br><div id="footer"><p align="center">Do you have any questions, suggestions or feedback? Ask your questions in the <a href="http://developer.db4o.com/Forums.aspx" target=_top>db4o forums</a>. Join the <a href="http://developer.db4o.com" target=_top>db4o community</a> for addional resources and news.<br><br><a href="http://www.db4o.com/" target=_top><small>www.db4o.com</small></a></p>.</div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></td></tr></table></div></body></html>