Blog Post RSS ?

Blogs » .NET » ObjectSpaces Explained
 

ObjectSpaces Explained

by miseldine

ObjectSpaces

Following the introduction to Whidbey article, this blog will feature some new, more advanced features and technologies in Whidbey.

The first technology to look at, and be prepared for, is ObjectSpaces. ObjectSpaces allow you to map your database tables to actual objects you can create and manipulate in your code. Yes, no more scrappy SQL statements :) But ORMs for .NET aren’t new. There are many implementations out there already, but ObjectSpaces is Microsoft’s first step into ORM (Object-Relational Mapping) and as you’ll expect from Microsoft, it’s clean in its design, easy to use, and simple to deploy.

So how does it work? Whereas before, where you’d create a database and some tables, and then use a DataReader or a DataSet to work with results from a SQL statement, using ObjectSpaces, you define mappings between your tables and a class you’ve created in your application which represents the same structure. And once you’ve created an instance of your class, you can tell ObjectSpaces to watch your instance, and update the database accordingly.

Let’s look in this in action. We’re going to create a very simple Zoo, to which we can add some animals and use a simple XML file as our data source.

The first step in any application where we wish to use ObjectSpaces is to write a class to represent any persistent objects we wish to use. In our case, we’ll have a class Animal which has the properties Species, Age, and Weight:

Our class needs to be abstract, as later we will be creating a specialisation of the object to use with the ORM. In this way, we can “override” some key methods in the class, such as the constructor, and ToString():

using System; using Microsoft.ObjectSpaces; namespace ZooSystem { ///

/// Summary description for Animal. /// public abstract class Animal { [UniqueId] public abstract int ID { get; set; } public abstract string Species { get; set; } public abstract string Age { get; set; } public abstract string Weight { get; set; } public virtual void OnCreate(int _id, string _species, string _age, string _weight) { ID = _id; Species = _species; Age = _age; Weight = _weight; } public override string ToString() { string res = String.Format( "Species: {0}\n", this.Species ); res += String.Format( "Age : {0 }\n", this.Age ); res += String.Format( "Weight : {0 }\n", this.Weight ); return res; } } }

Notice the [UniqueId] attribute: this makes the ORM treat our ID property like a primary key.

Once our class has been defined, we need to define the mappings between our data source and our class. Microsoft provide many examples of how to do this with traditional DBMS’s, so I thought it would be advantageous to show how easy it is to work with an XML file store. For this, we only need to tell ObjectSpace’s where to store our XML file:

zoo.xml

This can be saved in any file as long as our application can later access it at runtime. We’ll save it as map.xml as per Microsoft literature.

And that’s the setup complete. As I say, it is a little more involved for mapping direct to a DBMS (like SQL Server) however there are numerous articles regarding this.

Let’s move into implementing our Zoo using ObjectSpaces. To begin, we need to create an ObjectSpace referencing our mapping file, map.xml, which is taken as an argument in case its location later changes:

using System; using Microsoft.ObjectSpaces; namespace ZooSystem { public class Zoo { IObjectSpace objectSpace; public Zoo(string mapFile) { try { // Setup instance of an ObjectSpace with our mapping file. objectSpace = ObjectSpaceFactory.CreateObjectSpace(mapFile); } catch (Exception exception) { Console.WriteLine(exception); } }

We can now start the fun stuff :) To create a new Animal for our Zoo, we can let ObjectSpaces handle the interaction with the database for us:

public void addAnimal(int ID, string Species, string Age, string Weight) { Animal animal = null; try { animal = (Animal) objectSpace.CreateObject(typeof(Animal), ID, Age, Weight); // Commit the changes to the database objectSpace.BeginTransaction(); objectSpace.Update(animal); objectSpace.CommitTransaction(); } catch(Exception exception) { Console.WriteLine(exception); if(animal != null) { objectSpace.RollbackTransaction(); } } }

Notice the key points here. We create our object through the ObjectSpace specifying the abstract type we created earlier. After its creation, we can then begin a transaction. A transaction means that if an error occurs during our commitments to the database, we can rollback all changes we made during the transaction. In the code, this is achieved by catching any errors (say, we duplicated an ID) and then using RollBackTransaction to perform a rollback.

Let’s now allow for a change in a variable in an object, this time, to change the weight of an animal in our zoo. Before, this would mean an Update SQL command: not so with ObjectSpaces:

public void updateWeight(int ID, string newWeight) { Animal animal = null; string findFilter = "ID="+ID; animal = (Animal)objectSpace.GetObject(typeof(Animal), findFilter); try { objectSpace.BeginTransaction(); animal.Weight = newWeight; // Commit to DB objectSpace.UpdateAll(); objectSpace.CommitTransaction(); } catch(Exception exception) { objectSpace.RollbackTransaction(); } }

We can see how easy it is to find objects. We use a filter, which often resembles the WHERE clause of a SQL Select statement:

string findFilter = "ID="+ID; animal = (Animal)objectSpace.GetObject(typeof(Animal), findFilter);

We could also return collections of animals if we so wished:

reader = objectSpace.GetObjectReader(new ObjectQuery(typeof(Animal), "Species = 'Penguin'", "")); foreach (Animal animal in reader) { Console.WriteLine(animal.ToString()); }

Deleting objects is also performed in a similar fashion. As long as we enclose our modifications within a Begin and a Commit Transaction, our database will be updated accordingly:

public void deleteAnimal(int ID) { Animal animal = null; string filter = "ID='+ID; try { animal = (Animal) objectSpace.GetObject(typeof(Animal), filter); if(animal != null) { objectSpace.DeleteObject(animal); } // Commit the changes objectSpace.BeginTransaction(); objectSpace.Update(animal); objectSpace.CommitTransaction(); }

Stay tuned for other Whidbey topics!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Ping.fm
  • Twitthis

Related posts:

  1. X# to Xen to C Omega
  2. Javascript Inheritance
  3. Generic Dictionaries vs. the XmlSerializer
  4. Being a good little 404er
  5. .NET connecting to different databases…a request

This post has 7 responses so far

Sponsored Links