Friday, 15 June 2007

Most software projects start with an existing database.  It's not often that you get the chance to start from scratch and design the database the way you like it.  Now, creating Genome mappings for an existing database is a tedious job, but thankfully we have the Database Reverse Engineering Wizard for that.  So let's start Visual Studio 2005, and create a new Database Reverse Engineering project.

Genome will start a wizard.  Connect to Northwind, select all tables, accept the names for the projects or choose your own, change any options if you like (I opted to have Genome create default constructors) and click finish.  Genome will now generate two projects for you, one with classes for your domain model, and one for the mappings of those classes to database tables.

Let's have a look at some of the class file that the wizard generated for you. Open the Order.cs (or Order.vb if you selected VB.NET as your language of choice).

    1 using System;

    2 using TechTalk.Genome;

    3 using TechTalk.Genome.Mapping;

    4 using System.ComponentModel;

    5 

    6 namespace Genome.DataDomain

    7 {

    8     [TypeConverter(typeof(ExpandableObjectConverter))]

    9     public abstract class Order : Persistent

   10     {

   11         #region Primary Keys

   12 

   13         public abstract int OrderId { get; }

   14 

   15         protected Order()

   16         {

   17         }

   18 

   19         #endregion

   20 

   21         #region Scalar Fields

   22 

   23         public abstract Nullable<DateTime> OrderDate { get; set; }

   24         public abstract Nullable<DateTime> RequiredDate { get; set; }

   25         public abstract Nullable<DateTime> ShippedDate { get; set; }

   26         public abstract Nullable<decimal> Freight { get; set; }

   27         public abstract string ShipName { get; set; }

   28         public abstract string ShipAddress { get; set; }

   29         public abstract string ShipCity { get; set; }

   30         public abstract string ShipRegion { get; set; }

   31         public abstract string ShipPostalCode { get; set; }

   32         public abstract string ShipCountry { get; set; }

   33 

   34         #endregion

   35 

   36         #region Reference Fields

   37 

   38         public abstract Customer Customer { get; set; }

   39         public abstract Employee Employee { get; set; }

   40         public abstract Shipper ShipVia { get; set; }

   41 

   42         #endregion

   43 

   44         #region One To Many Associations

   45 

   46         public abstract Collection<OrderDetail> OrderDetails

   47         {

   48             get;

   49         }

   50 

   51         #endregion

   52 

   53         #region Many To Many Associations

   54 

   55         public abstract Collection<Product> Products

   56         {

   57             get;

   58         }

   59 

   60         #endregion

   61     }

   62 }

The file starts out with a couple of using declaration that refence the Genome namespaces. The Order class is annotated with the TypeConverter attribute, which is useful to display Genome objects in a property grid.  The first member we encounter is a property for the primary key of the Order entity, in this case a simple integer.  There's also the default constructor, which is protected because we are dealing with an abstract class. Then come a number of simple properties, nothing exciting.  After that it gets more interesting.

The Orders table has several foreign key contraints.  Those foreign keys are represented by references to related objects.  For example, the foreign key to the Employees table as mapped by a property of type Employee.  We have the other direction as well: the OrderDetails table has a foreign key to the Orders table.  This results in the Order class having a collection of OrderDetail objects.  If you take a look at the OrderDetail class, you will find it has a property of type Order for its side of the relation.

Lastly we have an m-p relation between the Orders and the Products tables, with the OrderDetails table as connection table.  Genome creates a collection of Product objects in the Order class, and a collection of Order object in the Product class.

By this time, you are probably wondering why the classes and all those properties are abstract. The reason becomes clear when we use Reflector to have a look at the assembly compiled by Genome.

For every class generated by the Database Reverse Engineering wizard, there are two classes in this assembly: one in a namespace starting with GenomeContextBoundProxy and one in a namespace starting with GenomeContextUnboundProxy.  The Genome runtime will use one or the other depending on the Genome Context. The distinction between the two kinds of proxies isn't that important, though. What is important is the fact that Genome uses the proxy design pattern. This all happens behind the scenes however, so as an application developer you will only deal directly with the abstract classes.

In the next installment, I'll use the Genome starter kit to create a web application that uses the two projects we just generated.

Posted by Dirk

Technorati Tags: object relational, getting started

Friday, 15 June 2007 11:16:50 (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  | 
 Sunday, 27 May 2007
I understand that PDC doesn’t deal with current or soon-to-be-released technology, and frankly, I didn’t epxect to see anything about Orcas there. I find their explanation weird, especially for two points.
Sunday, 27 May 2007 12:43:07 (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  | 
 Thursday, 15 March 2007

George Lawton contacted me at the end of February to ask some questions about O/RM as he was working on a story for theserverside.net. The story has now been published, and I think George Lawton and Jack Vaughn did a good job of providing an accurate analysis of the current situation of the O/RM market for .NET.

When I received George’s email, I was quite surprised that he was inquiring about the situation that people allegedly complain about O/RMs generating quick wins in the beginning that you pay dearly for at a later stage. In his article, you can read how strongly I disagree with this myth and I was pleased to see that other people quoted in his article feel the same.

George asked us the following three questions, which I found very interesting to discuss:

  • What specific features of Genome make it simpler to use, both initially and over time, than other O/RM tools?
  • What have been some of the major challenges in the use of O/RM tools, and what are the ways you have gone about addressing these?
  • What specific tips do you have to offer developers in getting the most out of using O/RM tools as part of the software development process?

Intrigued by his questions, I put together quite extensive replies – replies that may be of interest to others, too. Based on my answers to George, I have put together this article to outline our thoughts on the issues above and give some advice to developers who are evaluating O/RMs.

Thursday, 15 March 2007 15:59:23 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, 12 March 2007

The Singleton pattern represents a very common way of using lazy initialization with resources. Textbooks usually describe the Singleton as follows:

public class SingletonClass
{
  private static SingletonClass instance;
  public static SingletonClass Instance
  {
    get {
      if (instance == null)
      {
        instance = new SingletonClass(…);
        // do some initialization logic
      }
      return instance;
    }
  }
...
}

However, as any developer quickly realizes - implementing it in this way in a multi-threaded scenario is highly error-prone: if two threads attempt to access Instance at the same time (when it hasn't been created yet), both may run inside the if block and one of the threads will override the instance created by the other. As we tried to defend ourselves against this scenario, we changed the implementation as follows:

Monday, 12 March 2007 17:57:28 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  | 
Let’s be honest about it: getting to know Genome is a non-trivial undertaking. It may seem downright daunting. I want to share with you some of the things I did, hoping that someone might benefit from my experiences.
Monday, 12 March 2007 12:02:26 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, 26 February 2007

In my previous post I was discussing about how to mock test data for persistent objects mapped with Genome. Now I want to discuss how to provide this sample data in Blend so the designer building a front end with WPF actually sees how the UI would look like with data.

Genome | WPF
Monday, 26 February 2007 15:29:32 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Saturday, 24 February 2007

We’ve been working on a little research project recently with WPF and created a small (and hopefully handy) application where you can list your contacts synchronized from Microsoft CRM. We store the offline data in a SQL 2005 Compact Edition database and we access the data using Genome.

To make the experiment more exciting we involved a designer in the project, not only to design a cool UI using the features of WPF, but mainly to see how the collaboration between designer and developer works in reality.

Genome | WPF
Saturday, 24 February 2007 15:15:35 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, 20 February 2007

Yesterday we were releasing Genome 3.1. After making quite a big step from Genome 2.6 to 3.0 last November, I thought the 3.1 release would allow us to take a breath, do some polishing on the code and finish some of the stuff that just didn’t make it into 3.0.

How wrong I was.

The length of the What’s New for Genome 3.1 will easily tell you that this is not a minor upgrade. Some major improvements have been put into this release, so it is definitely worth upgrading to as soon as possible to 3.1 for everyone working with Genome.

Tuesday, 20 February 2007 17:03:07 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, 29 January 2007

I started working at TechTalk two weeks ago and one of my first tasks was – naturally – to get to know Genome. So I browsed through the tutorials and the quickstarts, and I watched the videos. Those gave me a general understanding of how to work with Genome. To get a real feel for it, I converted the data access layer of one of my pet projects to Genome. I know this pet project inside out, and it contains a couple of queries that are a bit more complex than your basis quickstart query. I felt that this was a good way to learn the details of Genome: take a project with a classic DAL that I know very well, and convert it to Genome while keeping all other aspects of the project. I struggled at first, but after a couple of days I came to grips with Genome and its query language and after that it went like a breeze.

What I like most about Genome is Query Decomposition. Suppose we have a Document entity and a Category entity. A Document can be assigned ("tagged") multiple categories, and there are many documents in each category - a classic m:p relation. In the dark ages of manual sql code, I'd have to write a stored procedure that gets all documents from the last 30 days. I'd have to write another stored procedure to get all documents in a certain category from the past 6 months. Thanks to genome, I have two select methods on my Document class for these scenarios. The first gets a set of documents from a specific time interval. The second gets a set of documents from a specific time interval that belong to a specific category. Using query composition, I can refactor these methods so that the second method calls the first method and does some more filtering on the result of the first method. Each idea is expressed only once in code. Genome takes care of executing just a single sql statement, even though I'm really calling two methods in my programming code. This is imo the real killer feature of Genome.

Posted by Dirk.

Monday, 29 January 2007 14:00:59 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, 05 January 2007

In the recent months there has been a lot of confusion in the community about what LINQ is and what it is not. If you discuss this topic with others and read through the blogs you will find a lot of different perspectives and opinions on LINQ.

Most of the questions and misconceptions about LINQ I have encountered are about mixing up LINQ with an O/RM system and not understanding the impact of LINQ to .NET based O/RMs.

This is a brief summary about LINQ and how it relates to O/RMs, using Genome as a concrete example.

Genome | Linq
Friday, 05 January 2007 18:55:23 (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |