So a couple weeks ago I decided to test a few changes made to SubSonic3 that fixed a LINQ evaluation bug related to medium trust. Using a simple console app on linux/mono, I tested basic data access to a SQLite database using repository mode, and to my surprise it worked!
I've always been a big fan of SubSonic since its 2.0 version, which I used for a mid-sized e-commerce site. With a totally rewritten core, 3.0 uses LINQ (language integrated query) for all of its data access providing a great alternative to Dblinq for the Mono platform.
SubSonic3 supports ActiveRecord, Repository, and Custom Linq modes, which give you the flexibility to build code-first or database-first. SubSonic3 is not an ORM (object relational mapping) like NHibernate, but it can behave like one when you use Repository Mode using POCO (plain old CLR object) representations of your tables. SubSonic handles the mapping and database query generation itself based on the database provider configured. Its intention is to allow you to build code-first and let the persistence of the object be non-critical to your application. It can even migrate your class definition changes (table schema) to the database automatically during runtime; however, it still has the flexibility to let you design your database with keys, indexes, and constraints yourself without using the automatic migration. The SubSonic website has a great demo showing this capability.
To make SubSonc3 truly database agnostic, you have to use Repository mode. Active Record and Custom Linq modes DO support multiple database engines, but they all require custom class generation which is hard-wired to those engines. So when you change database types like from MySql to MSSQL or vice-versa, you have to regenerate your classes.
With Repository mode, you simply change your connection string in the app.config. It will use the 2.0 Data Provider model provided by the database engine client and the definition of your POCO classes to determine the SQL syntax and schema to use. SubSonic is pre-wired with MSSql, SQLite, MySql, and a generic ANSI Sql syntax support. There's been lots of talk about implementing Oracle and PostgreSql, which may already work in ActiveRecord or LinqTemplates, but are not yet in the Core assembly for use with Repository.
Decoupled - Mocking for Unit Tests and Framework Independence
Another big advantage of Repository is the ability to decouple your data framework from your application completely. Since the POCO objects are not directly tied to SubSonic, they can be re-used with other frameworks like NHibernate or the latest Entity Framework 4 without touching a single line of application code. It also opens the door to mocking and testability. Dependency Injection frameworks like Unity or StructureMap work perfect for this.
So how about a sample?
This is a silly little test application that is neither pretty nor elegant, but it proves that this code will run on Mono 2.6.3 and 2.7 (trunk) with a SQLite database. It also uses Unity for dependency injection much like you would in Asp.NET MVC. Within the project, you'll find an AppService interface used to provide the definition for simple 'business' functionality. This is meant to be generic for the sample; but in a real application, I would breakdown the services by functional purpose. They all can share the same LinqRepository data interface, which provides basic rules for LINQ-based CRUD. SubSonic3 hooks right into that and is nearly transparent to the application with the exception of a few attributes on the domain objects. There are some placeholder Mock classes there and sample mappings in the code just for show.
You can also get the latest version from IWS Snippets project subversion.