Getting Started with Db4o: N Queries N Dealing with Object Activation Persisting .NET Object Data N Hot Tips and More
Total Page:16
File Type:pdf, Size:1020Kb
#53 Brought to you by... CONTENTS INCLUDE: n About db4o and Object Databases n Getting Started n Basic Database Operations Getting Started with db4o: n Queries n Dealing with Object Activation Persisting .NET Object Data n Hot Tips and more... By Stefan Edlich and Eric Falsken Visit refcardz.com 2008 Express editions are available for free download from ABOUT DB4O AND OBJECT DATABASES Microsoft. Running db4o requires only the .NET Framework to be db4o is the open source object database that enables installed. Some hosting environments, such as shared website developers to store and retrieve any application object with hosting providers, do not allow code to run with full trust. one line of code. When the environment is configured to run with reduced trust, The Object Database (ODB) arrived in the software industry all basic database operations require at least ReflectPermission with the advent of object oriented languages. The ODB is (MemberAccess and ReflectionEmit) for the classes and types primarily used as an application specific database in either being persisted. extreme scale systems or embedded systems where typical Required Libraries per Database Feature DBA activities are automated. Depending on the features your application requires, reference If you are familiar with object-relational mapping (ORM) tools, and distribute these assemblies when you distribute your then you are already an object database expert because many application: of the APIs and query languages are comparable. You will even (Required for all Installations) Db4objects.Db4o.dll find db4o both familiar and yet simpler to use as ORM tools as Client-Server Db4objects.Db4o.CS.dll there is no requirement for XML mapping, annotations or IDs. LINQ Db4objects.Db4o.Linq.dll db4o was introduced in 2000 with a focus on performance, Native Queries Db4objects.Db4o.NativeQueries.dll compactness, zero administration, simplicity and (the most Transparent Activation Db4objects.Db4o.Instrumentation.dll important of all) native object persistence. Developers were finally able to combine the power of a full database engine Run-time Optimization of LINQ, NQ, and TA requires with plain undecorated objects. the Mono.Cecil.dll and Cecil.FlowAnalysis.dll Note assemblies. Optimization can also be done at build- GETTING STARTED time using Db4oTool.exe. (see db4o Reference Documentation for usage) ObjectManager for Debugging The current version of db4o at the time of this Note Included in the db4o distribution you’ll find the installer for writing is version 7.8. ObjectManager Enterprise (OME) which, once installed, will www.dzone.com Get More Refcardz! integrate into your Visual Studio Environment and allow you db4o comes distributed as a few native .NET assemblies. Only to open and inspect, query, and edit (value types only ) object Db4objects.Db4o.dll is required for basic db4o operation. instances stored in your database file. Use the Visual Studio “Add Reference” command to add the necessary assemblies. Then use the Solution Explorer to locate the new reference, right-click and open the properties window to ensure that “Copy Local” is set to true for each db4o assembly. This will copy the necessary db4o libraries to your application’s bin folder automatically when compiling your the Database for Objects project. OEM Note Running db4o from the GAC is not supported. Jump Start Required Environment for .NET Developing with db4o requires only the .NET SDK version 2.0 ISVs and VARs Get a $36,000 OEM or better. (3.5 suggested) Jump Start Package for Free! Visual Studio 2008 or better is suggested for the best www.versant.com experience, but any .NET IDE will do. Microsoft Visual Studio db4o DZone, Inc. | www.dzone.com 2 db4o for .NET Connecting to a db4o Server BaSIC DaTABASE OPERATIONS After starting a db4o server instance, use either of the commands below to open a db4o client connection: A Complete Example // In-Process mode (embedded server) IObjectContainer db = IObjectContainer client = server.OpenClient(); Db4oFactory.OpenFile([filename]), ([config]); try{ // Client/Server mode (remote server) // Store a few Person objects IObjectContainer client = db.Store(new Person(“Petra”)); Db4oFactory.OpenClient([serverAddress], [port], [user], db.Store(new Person(“Gallad”)); [password]); // Retrieve the Person var results = db.Query<Person>(x => x.Name == “Petra”); Person p = result.First(); To close the client connection to the server: // Update the Person p.Name = “Peter”; client.Close(); db.Store(p); // Delete the person Storing an Object db.Delete(p); // Don’t forget to commit! db.Store(anObject); db.Commit(); db.Commit() } catch{ Just one line of code is all it takes. All of an object’s properties db.Rollback(); } and child objects will be stored. finally{ // Close the db cleanly Updating an Object db.Close(); } db.Store(anObject); db.Commit(); Create or Open a Database File Looks familiar? You can use the same Store(object) command IObjectContainer container = Db4oFactory.OpenFile([filename]); to update an object. One difference, however, is that db4o will (for performance reasons) not automatically check child objects While a db4o database file is open, it is locked and cannot be for changes. accessed by another application at the same time. By default, db4o will NOT descend into child objects. It’s important to know that db4o works best if you Store() must be called for each modified object Hot open the database file when you start working with Hot unless you change the default UpdateDepth (see Tip data, and close the db when all posible operations Tip the UpdateDepth parameter in the Configuration are completed. section, below) or configure cascading update for the persisted class. In traditional relational databases, it’s common to open a connection, get/update data, close connection, and then There is one more thing to be aware of: db4o uses an object’s perform your operation. Because db4o uses the native object native identity (referential identity) to identify an object (or referential) identity, it’s better to open the database or and map it to the stored instance of the object. This means connection when your application begins, do all your work, that there is only ever 1 instance of an object in memory for then close the database when your program is shutting down. each stored instance of the object. (per ObjectContainer or You’ll see why when we get to updating an object with our connection) This is important when dealing with class instances changes. that may come from ASP.NET ViewState, Web Services, Interop, or any other serialized source of object data. Starting a db4o Server By default, the db4o server runs in-process within your Avoid Confusion: Always make sure that the object application. To start a db4o server, place this code into your you are trying to update or delete was previously application: stored or retrieved in the database. Calling Store() with 2 User objects both with an ID of “jack” will IObjectServer server = Hot Db4oFactory.OpenServer([filename], [port]); Tip result in 2 separate instances. However, if you server.GrantAccess([user], [password]); retrieve the user, and modify the first instance, then To shut down the server: store it again, you will have only 1 updated instance server.Close(); in the database. The port parameter specifies the network port number. Acceptable values are any number above 1024 which are not Deleting an Object already in use. db.Delete(anObject); db.Commit(); Using Port 0 for your server creates an “Embedded” You didn’t think it was any harder than that, did you? Like Hot server which will not be available remotely. This is updates, db4o will not automatically delete child objects Tip useful for multi-threaded operations or web-server unless you configure cascading deletes for your object will style environments where you wish to handle remain in memory until the objects are refreshed or garbage parallel operations in a single process. collected. The GrantAccess() method must be called for each username/ Database Transactions password combination. It is not required at all for embedded Whenever you start making changes to your database (using servers. the Store() and Delete() commands) you are automatically in DZone, Inc. | www.dzone.com 3 db4o for .NET Commit() an open transaction. To close the transaction, use the // NQ Lambda Expression (.NET 3.5 syntax) method: var result = db.Query<type>( o => [boolean expression]); db.Commit(); // NQ Anonymous Method (.NET 2.0 syntax) IList<type> result = db.Query<type>( Your changes will be permanently saved. If you wish to cancel delegate(type o){ return [boolean expression]; or roll back any uncommitted changes, use the Rollback() }); method: db.Rollback(); Native Query Examples // Query all instances of a type. Useful for beginners: Rollback only undoes IList<User> result = db.Query<User>(); uncommitted changes in the database. It will not // Query Users by Name. IList<User> result = db.Query<User>(u => u.Name == “Joe”); undo changes to any currently loaded objects. // Query Users with at least 10 orders Hot So, when you call Rollback() you will not IList<User> result = db.Query<user>(u => u.Orders.Count >= 10); Tip see any difference to your objects. If concerned // Complex Query about consistency, use the Refresh(object) IList<User> result = db.Query<User>( u => u.Name.StartsWith(“Bob”) command to cause the objects to be refreshed with && (u.Country == “Canada” | | stored database values. u.Country == “USA” ); Closing a database cleanly will automatically call Commit() Sorting Native Queries for you, so any uncommitted transactions are committed Native Query results can be sorted by using an IComparer or a automatically. comparison delegate. Here is the query syntax: If the database is not closed cleanly, or if the application IList<User> result = db.Query<User>([predicate],[comparer]); crashes at any time and uncommitted (or incomplete) transactions are discarded. And here’s an example: // All users with “Smith” in their name QUERIES // sorted by name IList<User> result = db.Query<User>( u => u.Name.Contains(“Smith”), (u1, u2) => u1.Name.CompareTo(u2.Name) Query by Example (QBE) ); QBE lets you pass db4o an example object.