A SQL Server .NET ASP.NET MVC RESTful Web Services Facade – Part I

Did I get enough of the acronyms and key words in the header?  It looks like soup!  :O

This is a somewhat messy project to build a prototype layer around SQL Server. The reason for this, shockingly, is to allow for a SQL Server to be used by frameworks and systems that normally don’t or can’t access the database directly. In my particular scenario we’re working on getting Ruby on Rails running with JRuby in a Windows Environment. Because we will need to utilize a lot of SQL Server Databases, it seemed like a great idea to build out a layer over the SQL Server (or Servers) so that a Ruby on Rails Web App, ASP.NET MVC, or even a PHP or pure Javascript Application could access the data in the database. What better way to do that then to create a RESTful Web Services Facade over the database.

Some of you might be thinking “Why not use RIA Services?!?!?! Are you mad!!” Well, there is a big problem, RIA Services doesn’t work against SQL 2000 or SQL 2005, which is the database technology that this particular requirement dictated. Well, now that you have context, I’ll dig straight in to what I did building this prototype out.

Kick Out a SQL Server Database Project

I need some data, and a database, with just some of the standard junk you’d expect in a production database. One of the best ways to throw together a database in a really short amount of time, with data, is to use a SQL Server Database Project.

New Database Project (Click for larger image)
New Database Project (Click for larger image)

You might see this and think, “But you said that the facade is against a SQL Server 2000 or 2005 database!” Well, it is, but to get a database running locally and have this project type work, I’m using my local SQL Server 2008 Express installation. However, I’m limiting myself to data types primarily available to SQL Server 2000 and 2005. So no worries, this works just fine against those archaic databases.  😛

First I ran the following script to create the database and some sample tables with various data types.

[sourcecode language=”sql”]
DROP DATABASE SomeExistingOrMigratedDatabase
GO
CREATE DATABASE SomeExistingOrMigratedDatabase
GO
USE SomeExistingOrMigratedDatabase
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] DROP CONSTRAINT [FK_Person_Village]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Person]’) AND type in (N’U’))
DROP TABLE [dbo].[Person]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SomeFlatDenormalizedDataTable]’) AND type in (N’U’))
DROP TABLE [dbo].[SomeFlatDenormalizedDataTable]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Village]’) AND type in (N’U’))
DROP TABLE [dbo].[Village]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Village]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[Village](
[Id] [uniqueidentifier] NOT NULL,
[Village] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_Village] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SomeFlatDenormalizedDataTable]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[SomeFlatDenormalizedDataTable](
[Id] [uniqueidentifier] NOT NULL,
[StarzDate] [datetime] NOT NULL,
[Numerals] [int] NULL,
[Numberals] [int] NULL,
[Monies] [decimal](14, 4) NOT NULL,
[Day] [int] NOT NULL,
[Month] [int] NOT NULL,
[Year] [int] NOT NULL,
[BigNonsense] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Flotsam] [float] NULL,
[Jetsam] [float] NULL,
[SmallishText] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[BiggishText] [nvarchar](2999) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_SomeFlatDenormalizedDataTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Person]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[Person](
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[DateOfBirth] [datetime] NOT NULL,
[VillageId] [uniqueidentifier] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [FK_Person_Village] FOREIGN KEY([VillageId])
REFERENCES [dbo].[Village] ([Id])
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] CHECK CONSTRAINT [FK_Person_Village]
[/sourcecode]

Once the database and tables are created, import the database into the database project. To do this select the “Import Database Objects and Settings…” by right clicking the context menu on the Database Project.

Import Database Objects and Settings...
Import Database Objects and Settings...

Select the database just created and click on start. Once the script generation is done, navigate into the project directories and you will see the following scripts have been created.

Generated Scripts (click for larger image)
Generated Scripts (click for larger image)

Next create a new data generation plan in the Data Generation Plans folder (notice I already cheated and have one in the above image).

Creating a Data Generation Plan
Creating a Data Generation Plan

Open up the file this creates (I called mine BuildSomeData.dgen). In the file, note I selected the relationship between the Village and People Tables, and set the ratio to 60:1. When you change the data in the Village table it then automatically updates how much data will be generated for the People Table.

Data Generation Plan
Data Generation Plan

When all that is done, hit F5, select the database and the data will be generated. That gets us a database with data to use as an existing source. From here I’ll jump into creating the actual Facade Layer.

NOTES: Once you generate data, depending on how much you decided to generate, you may want to see how big your database is by using the sp_dbhelp stored procedure. I am however, unsure which versions of SQL Server this stored procedure is available in.

Code for this project is available here: https://github.com/Adron/ExistingSqlServerProject

ASP.NET MVC + Other Cleanup o’ The Day #1

Cleanup #1:

Here, let me help.  Replace this:

[sourcecode language=”csharp”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace Baseline
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801

public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

}

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
[/sourcecode]

With this:

[sourcecode language=”csharp”]
using System.Web.Mvc;
using System.Web.Routing;

namespace Baseline
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
[/sourcecode]

It’s not a huge cleanup, but it is cleaner. Got some other ideas to add? 🙂

ALT.NET Day #3 & #4

The main conference day of the ALT.NET Conference was pretty awesome. With sessions going on diving deep into technical topics and other things, like where the women are in technology. In addition to the great sessions multiple open source software projects where in progress at the same time. Being able to pair up or just review code with people on these projects was truly awesome!

The Open Source Projects

There were the stated open source project and I also started an additional project that I’ve titled Regiztry.  It’s located on Github at https://github.com/Adron/Regiztry.

The Various Sessions

The sessions covered a range of topics, from the RESTful technology with Glenn Block to Reactive Extensions with a host of extremely smart people laying out the usage.

I laid out a session also on .NET and bringing the gap with Ruby on Rails in the startup realm. This session I hope to elaborate on a little bit with a subsequent blog entry.

Overall, another kick ass year for the ALT.NET Conference. I enjoyed it a lot, as I see via Twitter that a lot of other people did too! Always a good thing! So until next year, to all those I met it’s been great, cheers!

ALT.NET 2011 Day #2

Day #2 kicked off a bit late for me. I arrived around 9:30am which was a bummer, but I at least got a bit of breakfast. The first session I went to was the reactive extensions session. Again though, I was late, so I ended up lost from the get go. That was unfortunate. In addition, all of my computers I brought were either unprepared (didn’t have a VM setup on the Mac yet) or broken (the Win7 box wouldn’t boot Windows Explorer anymore, thank goodness for Launchy). In spite of all that I got lunch with a host of devs at Black Raven Brewery. Absolutely great beer there!

After that the nitty gritty hacking finally got started! I attended the AppHarbor Session (@AppHarbor) given by the founders Michael (@friism) and Troels (@troethom) and decided to start a project myself. I immediately had some bad ass cohorts jump on the team! Eric Ridgeway, Ryan Eastabrook, and Joe Balfantz. We got started, in spite of massive OS and System Failures.

The project that we started is called Regiztry and is available via a repo on Github. The idea for this project actually started with a conversation I had with Rodica Buzescu (@rodica) several months ago. The idea is a contribution, or sharing system, to work with or help out startups. Keep in mind, they’re not all landing VC money! I’ll have more descriptions about how this project is going and better descriptions of it in the near future right here on Composite Code. If you’d like to help out startups, the project, or just code with some awesome people like Eric RidgewayRyan Eastabrook, and Joe Balfantz then message me on Github me.

Anyway, that’s what I got for day #2.

ALT.NET 2011 Day #1

Today kicked off with an early morning and a great workshop with Glenn Block (@gblock). The team he is working with has some great things coming for HTTP + REST + WCF that will really alleviate a lot of problems with WCF. In addition to that I’d bet that it will give Microsoft a chance to get back into the web API market.

That brings me to another topic that has come up a lot lately. Anyone that is in the startup scene or web development scene knows that Ruby on Rails has made an absolutely massive impact. I’m talking an impact like the invasion of Normandy! Microsoft has made many shifts to counter the ease, simplicity, and elegance of Ruby on Rails with things like ASP.NET MVC. Overall, the efforts have done a good job and been well received by .NET Developers in general.

However Microsoft has done a horrible job of getting aligned with the Internet startup space when it comes to web APIs. If you’re not sure what I mean, check out Twitter, Facebook, Apigee, and dozens of others. These are all companies that provide web APIs. Another notable one that has had some very money related impact, is the Best Buy API. Allowing people to hook into the API to really turn some revenue and make money. These APIs are almost always non-Microsoft stack technologies. When they are Microsoft, it is usually a hack around ASP.NET MVC or something of that sort to enable a more RESTful type API. With these additions to WCF this puts Microsoft back on some solid footing to compete in this space. I’m really looking forward to being able to pay around with these capabilities of WCF more – and hopefully sooner than later!

The second session of the day was a kind of modern anthropological study of development groups, their culture, and how processes, tools, and team qualities interplay among people. We ended up splitting into 3 (or was it 4) groups and went about various exercises.

I’m not sure the exact conclusions we came to during this session, but it was fun just to discuss each of our development groups. Ranging from topics of how we are forced to use Waterfall (and those clients often end up paying absurd amounts of money for things that should cost them less), how “pairing programming doesn’t exist” which gave us programmers that pair frequently a good laugh, and a whole host of other topics.

All in all, day one has started off great. I’m really stoked to be attending these workshops this year. Last year I was hard at work at… some client related debacle of crazy proportions, frantically looking forward to the weekend when the conference would start in earnest. But this year the team I work with are hittin’ the workshops early and doing the ALT.NET Conference completely.

Tomorrow is a session on AppHarbor, also known as Azure done right, and an xUnit Workshop by Brad Wilson that I’ll be attending. I’m already excited I’m not sure I’ll sleep. Until then, cheers.