April 25, 2012

How to get to Norway.

Bing is cool! (at least the map part)

I loaded up Visual Studio and fixed a developer key at www.bingmapsportal.com and then I spent an hour hacking with the Bing web services for routes.

I wanted to create an easy function to get directions from coordinate A to coordinate B and I wanted it to be asynchronous. Oh, yeah, I didn't care much about performance or any other details, just wanted results. After all a hack is a hack.

So. This is how I did it. Step by step.

1. Get a key to bing maps.


3. Created a route class with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapTools.BingRouteReference;

namespace MapTools
{
public class Routes
{
public delegate void RouteCompletedHandler(object sender, RouteFinishedEventArgs e);

public event RouteCompletedHandler RouteCompleted;

public void Calculate(Location start, Location end)
{
BingRouteReference.RouteServiceClient routeService = new
                                            BingRouteReference.RouteServiceClient();

RouteRequest routeRequest = new RouteRequest();
routeRequest.Credentials = new Credentials();
routeRequest.Credentials.ApplicationId = "[put your map key here!]";

routeRequest.Waypoints = new Waypoint[2];
routeRequest.Waypoints[0] = new Waypoint();
routeRequest.Waypoints[1] = new Waypoint();
routeRequest.Waypoints[0].Location = start;
routeRequest.Waypoints[1].Location = end;

routeService.CalculateRouteCompleted += new 
                                         EventHandler<CalculateRouteCompletedEventArgs>      
                                         (routeService_CalculateRouteCompleted);

routeService.CalculateRouteAsync(routeRequest);
}

void routeService_CalculateRouteCompleted(object sender,  
                                        CalculateRouteCompletedEventArgs e)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (var item in e.Result.Result.Legs.SelectMany(s=>s.Itinerary) )
{
stringBuilder.AppendLine(item.Text);
}
RouteFinishedEventArgs eventArgs = new RouteFinishedEventArgs()
                                     {RouteDescription = stringBuilder.ToString()};
RouteCompleted(this, eventArgs);
}
}
public class RouteFinishedEventArgs
{
public string RouteDescription { get; set; }
}
}

4. Created a client (winform is still quicker for trying out hacks):

Routes routes = new Routes();

public FormTester()
{
InitializeComponent();
routes.RouteCompleted += new 
                                Routes.RouteCompletedHandler(routes_RouteCompleted);
}
private void buttonExecute_Click(object sender, EventArgs e)
{
                        //Stockholm to Oslo
routes.Calculate(
                                new MapTools.BingRouteReference.Location() 
                                { Latitude = 59.32944, Longitude = 18.06861 },
                                new MapTools.BingRouteReference.Location() 
                                { Latitude = 59.94944, Longitude = 10.75639 });
}

void routes_RouteCompleted(object sender, RouteFinishedEventArgs e)
{
textBoxResults.Text = e.RouteDescription;
}

5. Sat back and enjoyed the directions:

<VirtualEarth:Action>Depart</VirtualEarth:Action> <VirtualEarth:RoadName>Gustav Adolfs Torg</VirtualEarth:RoadName> toward <VirtualEarth:Toward>Malmtorgsgatan</VirtualEarth:Toward>
<VirtualEarth:Action>Bear</VirtualEarth:Action> <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Norrbro</VirtualEarth:RoadName>
<VirtualEarth:Action>Turn</VirtualEarth:Action> <VirtualEarth:TurnDir>left</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Slottskajen</VirtualEarth:RoadName>
<VirtualEarth:Action>Bear</VirtualEarth:Action> <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Skeppsbron</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>Södermalmstorg</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>Västra Slussgatan</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>Hornsgatan</VirtualEarth:RoadName>
<VirtualEarth:Action>Bear</VirtualEarth:Action> <VirtualEarth:TurnDir>left</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Långholmsgatan</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>Liljeholmsbron</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>Södertäljevägen</VirtualEarth:RoadName>
At exit <VirtualEarth:ExitNumber>Södertäljevägen</VirtualEarth:ExitNumber>, <VirtualEarth:Action>take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>left</VirtualEarth:TurnDir> for <VirtualEarth:RoadName>E20 / E4</VirtualEarth:RoadName> toward <VirtualEarth:Sign>Helsingborg / Göteborg</VirtualEarth:Sign>
At exit <VirtualEarth:ExitNumber>Trafikplats Saltskog östra</VirtualEarth:ExitNumber>, <VirtualEarth:Action>take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> for <VirtualEarth:RoadName>E20</VirtualEarth:RoadName> toward <VirtualEarth:Sign>Strängnäs / Södertälje C / Göteborg</VirtualEarth:Sign>
<VirtualEarth:Action>At roundabout</VirtualEarth:Action>, <VirtualEarth:Action>take</VirtualEarth:Action> <VirtualEarth:ExitNumber>1st</VirtualEarth:ExitNumber> exit
At exit <VirtualEarth:ExitNumber>Trafikplats Gräsnäs</VirtualEarth:ExitNumber>, <VirtualEarth:Action>take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> for <VirtualEarth:RoadName>E18 / 249 / E20</VirtualEarth:RoadName> toward <VirtualEarth:Sign>Örebro / Göteborg / Lindesberg / Oslo</VirtualEarth:Sign>
At exit <VirtualEarth:ExitNumber>110A</VirtualEarth:ExitNumber>, <VirtualEarth:Action>take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> for <VirtualEarth:RoadName>E18</VirtualEarth:RoadName> toward <VirtualEarth:Sign>Örebro flygplats / Karlskoga / Oslo</VirtualEarth:Sign>
<VirtualEarth:Action>Pass through 2 roundabouts</VirtualEarth:Action>, remaining on <VirtualEarth:RoadName>Örebrovägen</VirtualEarth:RoadName>
<VirtualEarth:Action>At roundabout</VirtualEarth:Action>, <VirtualEarth:Action>take</VirtualEarth:Action> <VirtualEarth:ExitNumber>2nd</VirtualEarth:ExitNumber> exit onto <VirtualEarth:RoadName>E18 / E45</VirtualEarth:RoadName>
<VirtualEarth:Action>Keep</VirtualEarth:Action> <VirtualEarth:TurnDir>straight</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>E18 / Orrhagen</VirtualEarth:RoadName>
<VirtualEarth:Action>Pass through 4 roundabouts</VirtualEarth:Action>, remaining on <VirtualEarth:RoadName>Trøgstadveien</VirtualEarth:RoadName>
At exit <VirtualEarth:ExitNumber>Vinterbrokrysset</VirtualEarth:ExitNumber>, <VirtualEarth:Action>take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>left</VirtualEarth:TurnDir> for <VirtualEarth:RoadName>E6</VirtualEarth:RoadName> toward <VirtualEarth:Sign>Oslo</VirtualEarth:Sign>
<VirtualEarth:Action>Keep</VirtualEarth:Action> <VirtualEarth:TurnDir>straight</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>E6</VirtualEarth:RoadName>
<VirtualEarth:Action>Road name changes</VirtualEarth:Action> to <VirtualEarth:RoadName>150 / Hjalmar Brantings Vei / Ring 3</VirtualEarth:RoadName>
<VirtualEarth:Action>Take</VirtualEarth:Action> ramp <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> toward <VirtualEarth:Sign>Tåsen / Maridalen</VirtualEarth:Sign>
<VirtualEarth:Action>At roundabout</VirtualEarth:Action>, <VirtualEarth:Action>take</VirtualEarth:Action> <VirtualEarth:ExitNumber>2nd</VirtualEarth:ExitNumber> exit onto <VirtualEarth:RoadName>Rolf Wickstrøms Vei</VirtualEarth:RoadName>
<VirtualEarth:Action>At roundabout</VirtualEarth:Action>, <VirtualEarth:Action>take</VirtualEarth:Action> <VirtualEarth:ExitNumber>1st</VirtualEarth:ExitNumber> exit onto <VirtualEarth:RoadName>Maridalsveien</VirtualEarth:RoadName>
<VirtualEarth:Action>Turn</VirtualEarth:Action> <VirtualEarth:TurnDir>right</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Blåsbortveien</VirtualEarth:RoadName>
<VirtualEarth:Action>Turn</VirtualEarth:Action> <VirtualEarth:TurnDir>left</VirtualEarth:TurnDir> onto <VirtualEarth:RoadName>Ustvedts Vei</VirtualEarth:RoadName>
<VirtualEarth:Action>Arrive</VirtualEarth:Action> at <VirtualEarth:WaypointName>Ustvedts Vei</VirtualEarth:WaypointName>

So now you know how to get to Norway...

PS. Just let me know if you want the full code.

April 21, 2012

My top ten list on how to succeed with large projects. (1)

Do not forget the customer

Customers pay for your fun job, they know the problem area much better than you do and they share an interest with you to make a good program. Do not forget them!

In an ideal world customers should be as entwined in the project as the developers, project managers, architects... For some reason there is usually a need to fight with them a bit to make them a part of the project. Try telling them that the project costs so many millions and that without the know how for a comparatively small cost the project might fail. 

The project needs the customer. Their involvement brings so many vital benefits and very few hazards. You minimize the risk that you will discover that you misunderstood what the system was supposed to do after a few months, you solve problem areas much quicker and you have nicer coffee breaks. 

The customer on the other hand will hopefully start to understand the fabric of your work and he will be reassured to see that you are not only taking coffee breaks all of the time. At least not without him.

April 20, 2012

My top ten list on how to succeed with large projects. (2)

Keep expectations where they should be

There are many pitfalls when time estimating or promising features. You may be overly enthusiastic and get swept away by the enthusiasm, you may believe too much in your own abilities, you are afraid to tell the customer the real costs, you simplify the impact of the uncertainties and risks in the project or you simply forget about all the boring stuff that needs to find time as well such as testing, documentation, meetings...

There is a saying that you should multiply your estimates with pi, but I don't buy that. Better to learn how to estimate correctly and to know when not to estimate than to just tell the customer that the project will cost three times as much as you believe. In the end no one will be happy if the project gets delayed.

Honesty is a good trait. If you cant make an estimate say so. And try to keep your hybris and megalomania pinned down, so common traits among developers. After all we are a bit like gods, being able to create anything we can imagine in the virtual world called a computer.

April 19, 2012

My top ten list on how to succeed with large projects. (3)

Industrialize!

Sometimes it seems like it's rude not to include everyone in all parts of the project resulting in a development method where every developer is part of the process from GUI down to the database and the external services. 

Software development is at the same level as how cars were produced before the T-Ford. They are built by hand, painstakingly, and they still end up with quality flaws that would have been corrected with a more industrial approach.

Software development methods are of course getting better, but still membership in a project is something that puts developers in a position where they are supposed to work eight hours a day from the start until the end of the project. It matters less if they are the best for the current task or not, yet in a project there are some highly specialized tasks that needs specialized skills like usability design, deployment, graphic design, performance testing etc.
How many of you haven't seen a good developer spending weeks on making lousy graphic design, buttons and the like? (For some reason few people seem to have strong skills in design and programming at the same time)

On the other end of the spectra we have projects where you appoint a manager or an architect even though you know that his or hers commitment is limited in time or effort. Putting an architect for the first months only in a big project will only damage it. Leading roles in a project should be long term.

So how do we get to a point where we can industrialize the process of making software?

I think that one important step is to sell more solutions than resources to the customer. If you sell a consultant for six months to a customer, he will stay there. If you sell a solution that will take six months to complete you will have a freedom in the staffing and you have at least a possibility to put the right person at the right task. Another important step is to have simple rules of thumb on staffing a project always striving to put the right person on the right spot with the right level of commitment.


April 18, 2012

My top ten list on how to succeed with large projects. (4)

Responsibility makes better software

Last entry on this list concerned losing control over the project, this one shares the subject. Having control is a key to not only manage and finish a high quality project in time, it is also vital for the developers ability to sleep at night. 
So who's fault is it if something goes wrong? If the database ends up without normalization and the business layer turns up as a huge mass of code with ugly dependencies in every direction. 
In many projects that is a question that no one can answer. "It just grew out to be like this" or "we had so little time" are common and sometimes valid excuses.

I believe in responsibility. I believe that someone should be responsible for the structure in the database, in the business layer, the unit testing and that everyone follows the GUI guidelines of the project.

The reason for this is not because I like to punish people, the reason is that issues have a tendency to fall between people, to disappear and gather dust. This can to some extent be removed with clear responsibilities. If this is my area I want it to be as good as possible, that would at least be my instinct.

I wouldn't want to be caught up with tables without primary keys in my database and I sure as hell would want my business entity to be as easy to manage as possible, something that is best achieved by doing it right.

Responsibility makes better software.

April 17, 2012

My top ten list on how to succeed with large projects. (5)

If you lose the map you're lost

Have you ever been in a project where the developers lost the big picture? It is tough to get back from.

If the map, the architectural blueprints, are lost it is like a disease out of control. The quality goes quickly from so-so to non-existing. People begin to duplicate code instead of using existing mechanisms, they put methods in other classes than they logically belong to and the cohesion gets more and more strongly coupled when the developers skip the architecture and shoots from the hip. And with bad code, unhappy coders.

The software architecture is more than just how the system was envisioned once in the beginning of the project. 

It is a guideline that should be kept alive throughout the project. It is the language of the project.

The architecture should continually be communicated throughout the project. A social gathering just as important as the scrum meetings or the project meetings. Focus on what should be where and how to reuse existing code. Focus on black box issues, code discussions beyond the classes and their interfaces are less helpful. As a developer I don't really care how a method is constructed as long as it accepts the arguments I want to change and do what I want it to do. Don't get stuck in details. I have seen too many projects where the  discussions is more about using tabs or spaces for indenting than entities. 

So to summarize: I propose an overview of the architecture every monday morning at 09:00! Keep the map alive!

April 16, 2012

My top ten list on how to succeed with large projects. (6)

Demand a TCO for system architectures.

Do you remember TCO? It stands for Total Cost of Ownership and was common in the nineties for corporation calculating the total cost of their computer and software investments. The calculus should not only include the initial cost of stuff, but also costs for management, licences, infrastructure, education, salaries etc. 
I believe it is time to take this paradigm to system architectures.
Architects and developers are usually geeks with an interest in their job. They like programming. 

And they also like everything that is new and hot and they are very curious about trying stuff. 

Stuff that stays interesting for a month or so until the next new cool stuff shows up.

Stuff that ends up deep in the architecture of the systems they create. 

Stuff that in the end can cost the customer a lot of money and what is bad for the customer is bad for the developers. (even if it can give them a longer project in the short term)

I don't mean that you never should adapt new programming paradigms, add third party libraries or use new patterns to build the software. System development is about evolution, otherwise we might all just stay programming COBOL.

I do however mean that you should think before you do it.

Think in terms of "How much do I gain by using this new stuff?", "How much will it cost?", "How much more complex will the code get?", "Can we find developers that know this stuff or will people make shortcuts and further degrade the architecture?", "Will this new stuff be legacy in a few years or will it stay?". "Do we really, really need this?", "Which are the alternatives?"

In short make a quick TCO-analysis. Don't just buy the buzz words without thinking.

April 13, 2012

My top ten list on how to succeed with large projects. (7)

#7 Scrum slowly in the beginning.

I really like scrum or other agile methods, but I am not one of the religious fanatics. Scrum like any method has its strengths and weaknesses. Scrum is time boxed and is focused on dividing a task into smaller subtasks that can be given time estimates. It is an effective method when the domain is well known. The focus on what instead of how can however be a problem when making the system analysis. It is all too easy to forget that you cannot build a system without taking time to make up a lasting architecture, simple enough to be understood and rich enough to cater for the whole system, not just for a sprint. Although agile methods have mechanisms for system analysis, it just doesn't seem like a first citizen. Agile methods are focusing on keeping the work and produced code up, not for taking it slow and think. But no thinking makes a stupid system architecture.
Don't do until you know what to.

System architectural decisions early in a projects lifetime are decisions that lives for a long time and are hard to change. It can be mistakes that will cost many, many hours.

So use scrum, but take it slow in the beginning. Make time for some thinking.

April 12, 2012

My top ten list on how to succeed with large projects. (8)

#8 Cut up the cake

Have you also been in a project where you afterwards said stuff like "yeah, we should have done it in smaller pieces" or "I don't understand the system anymore"?

Software systems are like tigers, they start all cuddly and sweet but suddenly you have a 1000 pound man-eater in your office. And once you lose control over the beast it takes lots of effort to regain it.
The bigger the system the harder to control, but somehow, even though we all know about the importance of using modules when coding, it is easy that the system gets to big to understand.
Modularized code is almost as old as programming itself, but to use it you need to think before you start coding and you need to continue thinking while you add new functionality. 

Common sense, right?

April 11, 2012

My top ten list on how to succeed with large projects. (9)

#9 Isolate

For me succeeding with a project is to reach high quality and stay within budget. To be able to take responsibility for any time schedules and to be able to reasonably well give a good guesstimate on how long  time a project will take you need to know what you are calculating on.

You can never calculate time for external projects. Still most software systems don't live on their own, they have dependencies to external systems, systems that can be unstable, changing or not even constructed yet.

It is a problem. A problem that can be yours if you don't handle it.

If you isolate your software and never make demands of any other functionality than that contained in your system it shouldn't be a problem. But in real life system borders can be unclear and vague and if you don't code for isolation it can be hopeless to see where a problem spurs from.

Some tips:

  • Keep your own data carriers. Loosely coupled code are tenfold more important when working with external components.
  • Build for robustness. Treat all external services as unreliable and always code with that in mind.
  • External frameworks and components can be nice, but they also makes your system more depending on external systems. Think twice.

April 10, 2012

My top ten list on how to succeed with large project (10)s.

#10 Treat the requirement document as an evidence in an upcoming murder trial. With you as accused.

Sellers are sellers and they will always be sellers. Their job is to land deals, sell in stuff and in many cases get a fat provision for doing so. There is a small gap between selling and delivering a solution.
That responsibility lays on the project manager and below him, the system architect and the developers. To add to the problem more and more projects sells for a fixed or semifixed price, risking to give the development crew an impossible task at an impossible price.

What will be constructed is specified in the requirement document. If you want a cv that will not scare away your future employers (because the risk is that you will get sacked when a fixed price project takes a year too long at a cost of x millions) you need to treat this document with utmost respect, because if shit hits the fan this document may prove to be your executioner or your saviour. 
Fuzzy requirements will be the foundation for a fuzzy system and I am not talking fuzzy logic here. Responsibility is a dangerous beast, best treated with respect.

When the project lands on your lap after the seller sugarcoated it, it is up to you to make sure that no work is started without clear requirements. The first job in a project with fuzzy requirements should be to sharpen the specifications, no matter if it is done with analysis, prototyping or with customer workshops. Fixed prices should not be negotiated until customer and consultant agrees in a sufficient detailed way what is going to be built. 

The same rules applies when building the system, beware of gliding requirements or demands that are not specified in the requirement document. You are promising to fulfill whats in this document and you are obliged to make the customer take the consequences as soon as he wants functionality that's not included in this document. 

Of course it goes without saying that accepting a requirement document when you know it lacks vital functionality that the customer will have to pay for later is both unprofessional and unethical. 

You will not keep customers by backstabbing them.

Common sense. Only do when you know what to. 
Wonder why common sense is such a rare commodity. Maybe it has something to do with money.

April 9, 2012

Next project starting

A year ago I released uBirder on the windows phone market. An app for birders, giving them possibility to list all species in a specific area, make observations and get information about bird species. I have been thinking a lot about making a second version on it and today I feel the ideas are mature enough to start working. The plan is to make public webservices hosted on azure and to also release clients for the windows phone and windows 8. I will try to publish glimpses of the work on the blog. (I guess I will be tied up with the project for half a year or something)

But now! Time to create the database! (of course with the help of .CreateSchema)

April 6, 2012

Create Schema 1.0.2 out

I just fixed a few bugs and put a new version of CreateSchema out here. It should fix the relations from generic lists as well as giving a more normalized view of unary relations.

The future is here!

Look at this!
In 20 years people will look back at it and see it as an important stepping stone in the process of turning us all into cyborgs. Microsoft, where are you???? :)

The logic behind the .CreateSchema extension

As I stated earlier, the modelling of a class hierarchy to tables is a lot about guessing. So which guesses do the CreateSchema extension make?

Datatypes

The extension tries to follow the mapping on this page. But of course, since one C# data type maps to several data types in sql server guesses are made. Strings for example maps to nVarChar(8000) and decimal maps to Decimal and not to Money in SQL server. You will have to check the source code for a full list.

Failures

Stuff that the CreateSchema cant handle will end up in the comment field in the bottom of the generated script.

IDs 

Every table gets an primary key column named ID of either Int with Identity or GUID depending on settings, the default is Int with Identity. If you are into other name standards or want other fields acting as keys you will have to edit the SQL. Even relational tables get an ID for a primary key, not the more common way of having an aggregate key consisting of the primary keys of the related tables.

Collections

Every collection of value types or the supported reference types will be broken out into a new table with an ID and a Value field of the type of the collection. The extension currently only do this for generic lists (List<>) so if you have dictionaries or arrays for example they will end up on the failure list. 

Relations

There is no way to really know how to translate relations into tables, there is no semantic notions in c# whether a list of objects symbolize a one to many relation or a many to many relation. I am currently only making many to many relations when there are list of objects pointing from each direction to each other. Eg. object A has a list of object B and object B has a list of object A. 

Enums

Enums are currently broken out to a table much like the collections.

Class hierarchies

I support two ways to map class hierarchies to tables. I either keep class hierarchies and let tables generated by subclasses have all the fields of the superclass, duplicating the data or I split the hierarchies letting the tables generated by subclasses only contain their own properties along with a foreign key to the super class. The default strategy is to split hierarchies.

April 5, 2012

A little hack to simplify my coding...

I am in the beta testing phase of my .CreateSchema-extension, but I still found the guts to put it on CodePlex.

So what is it and how does it work?

Well let's start with a sample object diagram, let us say that you are doing software for a travel company (since this seems to be the standard practice project in swedish universities).

Your object diagram could look somewhat like this:
You got the typical customer with a link to itself and a subclass with a discount, you got a company object that can be either a cruise company, an airline or a charter company. The companies offers travels and one or several persons can write some contracts with some travels. Basic stuff! :)

So now the model is roughly finished and you need to get it into SQL server for persistance. That would mean some few hours of more or less non-creative work, mostly copying properties from c# to SQL Server. Boring, boring job... So (fanfare) enter the CreateSchema extension found here. And then you simply add a reference to the ObjectScriptingExtensions.dll, add a using ObjectScriptingExtensions; to your code and write: 
Traveller traveller = new Traveller();
string s = traveller.CreateSchema();
The string returned by the CreateSchema() will be a long SQL statement that looks like this:

/****** Object:  Table [dbo].[Traveller]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Traveller]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FirstName] NVARCHAR(4000) NULL,
[LastName] NVARCHAR(4000) NULL,
[FullAdress] NVARCHAR(4000) NULL,
[Telephone] NVARCHAR(4000) NULL,
[Age] INT NOT NULL,
[FKAssociatedTravellers] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[Contract]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Contract]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[ContractReference] UNIQUEIDENTIFIER NOT NULL,
[FKItems] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[ContractItem]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[ContractItem]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[Price] DECIMAL(18,2) NOT NULL,
[PurchaseDate] DATETIME NOT NULL,
[Duration] TIME NOT NULL,
[FKPurchasedTravel] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[Travel]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Travel]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[Destination] NVARCHAR(4000) NULL,
[BasePrice] DECIMAL(18,2) NOT NULL,
[FKCompany] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[Company]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Company]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[Name] NVARCHAR(4000) NULL,
[OrganisationNumber] NVARCHAR(4000) NULL

)

GO
/****** Object:  Table [dbo].[CruiseCompany]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CruiseCompany]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FKCompany] INT NOT NULL FOREIGN KEY REFERENCES [Company]([ID]),
[FKSeasWithOfferedCruises] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[CruiseCompany_SeasWithOfferedCruises]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CruiseCompany_SeasWithOfferedCruises]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[Value] NVARCHAR(4000) NULL

)

GO
/****** Object:  Table [dbo].[CharterCompany]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CharterCompany]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FKCompany] INT NOT NULL FOREIGN KEY REFERENCES [Company]([ID]),
[FKTypeOfCharter] INT NOT NULL

)

GO
/****** Object:  Table [dbo].[CharterType]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[CharterType]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[Name] NVARCHAR(4000) NULL

)

GO
/****** Object:  Table [dbo].[AirlineCompany]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[AirlineCompany]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FKCompany] INT NOT NULL FOREIGN KEY REFERENCES [Company]([ID]),
[MajorHub] NVARCHAR(4000) NULL

)

GO
/****** Object:  Table [dbo].[VipTraveller]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[VipTraveller]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FKTraveller] INT NOT NULL FOREIGN KEY REFERENCES [Traveller]([ID]),
[Discount] REAL NOT NULL

)

GO
/****** Object:  Table [dbo].[Contract_Traveller]    Script Date: 2012-04-05 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Contract_Traveller]
(
[ID] INT IDENTITY NOT NULL PRIMARY KEY,
[FKTraveller_Contract] INT NOT NULL,
[FKContract_Traveller] INT NOT NULL

)

GO

/****** Object:  ForeignKey [Contract_Traveller_Contract_Contract_Traveller_FKTraveller_Contract]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[Contract_Traveller]  WITH CHECK ADD  CONSTRAINT [Contract_Traveller_Contract_Contract_Traveller_FKTraveller_Contract] FOREIGN KEY([FKTraveller_Contract])
REFERENCES [dbo].[Contract] ([ID])
GO
ALTER TABLE[dbo].[Contract_Traveller] CHECK CONSTRAINT [Contract_Traveller_Contract_Contract_Traveller_FKTraveller_Contract]
GO
/****** Object:  ForeignKey [Contract_Traveller_Traveller_Contract_Traveller_FKContract_Traveller]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[Contract_Traveller]  WITH CHECK ADD  CONSTRAINT [Contract_Traveller_Traveller_Contract_Traveller_FKContract_Traveller] FOREIGN KEY([FKContract_Traveller])
REFERENCES [dbo].[Traveller] ([ID])
GO
ALTER TABLE[dbo].[Contract_Traveller] CHECK CONSTRAINT [Contract_Traveller_Traveller_Contract_Traveller_FKContract_Traveller]
GO
/****** Object:  ForeignKey [CruiseCompany_CruiseCompany_SeasWithOfferedCruises_CruiseCompany_FKSeasWithOfferedCruises]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[CruiseCompany]  WITH CHECK ADD  CONSTRAINT [CruiseCompany_CruiseCompany_SeasWithOfferedCruises_CruiseCompany_FKSeasWithOfferedCruises] FOREIGN KEY([FKSeasWithOfferedCruises])
REFERENCES [dbo].[CruiseCompany_SeasWithOfferedCruises] ([ID])
GO
ALTER TABLE[dbo].[CruiseCompany] CHECK CONSTRAINT [CruiseCompany_CruiseCompany_SeasWithOfferedCruises_CruiseCompany_FKSeasWithOfferedCruises]
GO
/****** Object:  ForeignKey [CharterCompany_CharterType_CharterCompany_FKTypeOfCharter]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[CharterCompany]  WITH CHECK ADD  CONSTRAINT [CharterCompany_CharterType_CharterCompany_FKTypeOfCharter] FOREIGN KEY([FKTypeOfCharter])
REFERENCES [dbo].[CharterType] ([ID])
GO
ALTER TABLE[dbo].[CharterCompany] CHECK CONSTRAINT [CharterCompany_CharterType_CharterCompany_FKTypeOfCharter]
GO
/****** Object:  ForeignKey [Travel_Company_Travel_FKCompany]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[Travel]  WITH CHECK ADD  CONSTRAINT [Travel_Company_Travel_FKCompany] FOREIGN KEY([FKCompany])
REFERENCES [dbo].[Company] ([ID])
GO
ALTER TABLE[dbo].[Travel] CHECK CONSTRAINT [Travel_Company_Travel_FKCompany]
GO
/****** Object:  ForeignKey [ContractItem_Travel_ContractItem_FKPurchasedTravel]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[ContractItem]  WITH CHECK ADD  CONSTRAINT [ContractItem_Travel_ContractItem_FKPurchasedTravel] FOREIGN KEY([FKPurchasedTravel])
REFERENCES [dbo].[Travel] ([ID])
GO
ALTER TABLE[dbo].[ContractItem] CHECK CONSTRAINT [ContractItem_Travel_ContractItem_FKPurchasedTravel]
GO
/****** Object:  ForeignKey [Contract_ContractItem_Contract_FKItems]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[Contract]  WITH CHECK ADD  CONSTRAINT [Contract_ContractItem_Contract_FKItems] FOREIGN KEY([FKItems])
REFERENCES [dbo].[ContractItem] ([ID])
GO
ALTER TABLE[dbo].[Contract] CHECK CONSTRAINT [Contract_ContractItem_Contract_FKItems]
GO
/****** Object:  ForeignKey [Traveller_Traveller_Traveller_FKAssociatedTravellers]    Script Date: 2012-04-05 ******/
ALTER TABLE [dbo].[Traveller]  WITH CHECK ADD  CONSTRAINT [Traveller_Traveller_Traveller_FKAssociatedTravellers] FOREIGN KEY([FKAssociatedTravellers])
REFERENCES [dbo].[Traveller] ([ID])
GO
ALTER TABLE[dbo].[Traveller] CHECK CONSTRAINT [Traveller_Traveller_Traveller_FKAssociatedTravellers]
GO

/****** Did not script following | Script Date: 2012-04-05 

******/



It is a lot of SQL that you dont have to write yourself!

And if you look at the table diagram it will look like this after executing:



Almost correct! But as object relational mapping is a guess work you should modify this to suit your needs (and also there's still some bugs in the generator logic). See it as a way to generate a skeleton of your tables rather than the truth of how you should serialize your objects. Hope you try it out, have fun and maybe even fix the bugs at CodePlex for me! :)

PS. I made it on a big object model just to show that the codes handles it pretty well, start out with a single class first.

See you!