In this intro I'll create a vanilla Silverlight 4 application, hosted in a WCF Service, and wired up to SQL Server 2008 with the open source NHibernate ORM tool. I'm not going to dive into the weeds here. I just want to show the basics.

Prerequisites:

* Visual Studio 2010 Beta 2
* Silverlight 4 Tools for VS 2010
* NHibernate 2.n
* SQL Server 2008

In Visual Studio create a new project using the Silverlight Application project template. When prompted, choose to host the project in a new web site with the default ASP.NET Web Application Project type. I'll call it "ConcertMusic.Web" because we're going to fetch a list of classical music instruments from a database table and display them in a SL DataGrid. Do not enable .NET RIA Services.

After the project template unfolds right-click the ConcertMusic.Web and create a WCF Service using the Silverlight-enabled WCF Service template. I'm not going to get into WCF here but you'll want to create a contract interface, configure the service behavior and bindings, and perhaps add a ClientAccessPolicy.xml file. Here's my service contract:

   1:  namespace ConcertMusic.Web
   2:  {
   3:      [ServiceContract(Namespace="http://ConcertMusic.Web/2010/07")]
   4:      public interface IConcertMusicService
   5:      {
   6:          [OperationContract]
   7:          IList<Instrument> GetInstruments();
   8:      }
   9:  }

Now let's configure NHiberate. Add references to the required NHibernate assemblies: NHibernate.dll, log4net.dll, Iesi.collections.dll, and Antlr3.Runtime.dll. (Optionally, include Castle or Spring assemblies if you want to support lazy loading. I'm not going to get into that here.)

In Web.config add the plumbing to configure NHibernate:

   1:  <configuration>
   2:   
   3:    <configSections>
   4:      <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
   5:    </configSections>
   6:   
   7:    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
   8:      <session-factory>
   9:        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
  10:        <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
  11:        <property name="connection.connection_string">Data Source=SERVER_INSTANCE;Initial Catalog=DatabaseName;Integrated Security=SSPI</property>
  12:        <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
  13:        <property name="show_sql">false</property>
  14:        <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
  15:      </session-factory>
  16:    </hibernate-configuration>

Ok so we've got the NHibernate assemblies referenced and we've configured it the project. Let's start at the database and work our way forward. First, we've got a table of musical instruments in the database:

   1:  CREATE TABLE [dbo].[Instrument](
   2:      [ID] [int] IDENTITY(1,1) NOT NULL,
   3:      [Name] [nvarchar](50) NULL,
   4:      [Description] [nvarchar](120) NULL,
   5:   CONSTRAINT [PK_Instrument] PRIMARY KEY CLUSTERED 
   6:  (
   7:      [ID] ASC
   8:  )WITH 
   9:  (PAD_INDEX  = OFF, 
  10:  STATISTICS_NORECOMPUTE  = OFF, 
  11:  IGNORE_DUP_KEY = OFF, 
  12:  ALLOW_ROW_LOCKS  = ON, 
  13:  ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  14:  ) ON [PRIMARY]
  15:   
  16:  GO

We need to do two things to map the table to a plain old CLR object (POCO) in our application. We have to create the POCO class and then we have to create a mappping file that tells NHibernate how to create an instance of that class from the data store. Here's our simple POCO class:

   1:  [DataContract]
   2:  public class Instrument
   3:  {
   4:      public Instrument() { }
   5:   
   6:      [DataMember]
   7:      public virtual int ID { get; set; }
   8:   
   9:      [DataMember]
  10:      public virtual string Name { get; set; }
  11:   
  12:      [DataMember]
  13:      public virtual string Description { get; set; }
  14:  }

Notice that we're using auto-implemented properties introduced in C# 3.0. Also, the class is implemented as a DataContract with DataMember properties. This is necessary if you want to bind an IList collection of Instrument objects to a Silverlight control. If you don't use DataMember attributes, then Silverlight will attempt to bind to the IL-generated backing fields instead and you'll get skinny blank rows in your DataGrid.

Ok, now let's create the NHibernate mapping file. It can live in the same place as the POCO or you can put your mapping files in a separate folder to keep them all together. It's up to you. The naming convention is [ClassName].hbm.xml:

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <hibernate-mapping assembly="ConcertMusic.Web" xmlns="urn:nhibernate-mapping-2.2">
   3:    <class name="ConcertMusic.DomainModel.Instrument, ConcertMusic.DomainModel" table="Instrument" lazy="false" >
   4:      <id name="ID" type="Int32" column="ID">
   5:        <generator class="identity" />
   6:      </id>
   7:      <property name="Name" column="Name" />
   8:      <property name="Description" column="Description" />
   9:    </class>
  10:  </hibernate-mapping>

I'm not going into a long explanation of this file. Read the NHibernate docs for a detailed specification. For now I'll just say that ID is described as a synthetic key (identity column), and Name and Description are mapped one-to-one to identical column names in the table. Pretty straightforward. Very important! Change the build action of this xml file to make it an embedded resource. It needs to be compiled into the assembly in order by NHibernate to find it at runtime.

NHibernate uses an ISessionFactory to talk to the database. Just like IDbConnections in ADO.NET, these are very expensive to set up so you don't want to set them up and tear them down with every transaction to the database. The best practice is to create them once and then hold onto them during the lifetime of the application. Here I'm using a Singleton pattern to wrap the factory in a helper class:

   1:  public class NHibernateHelper
   2:  {
   3:      public static readonly ISessionFactory SessionFactory;
   4:   
   5:      static NHibernateHelper()
   6:      {
   7:          Configuration cfg = new Configuration().AddAssembly("ConcertMusic.DomainModel");
   8:          SessionFactory = cfg.Configure().BuildSessionFactory();
   9:      }
  10:   
  11:      public static ISession OpenSession()
  12:      {
  13:          return SessionFactory.OpenSession();
  14:      }
  15:  }

In line 7 I'm adding the assembly ConcertMusic.DomainModel to the NHibernate configuration. This is to tell NHibernate where my [ClassName].hbm.xml mapping files live. I created a separate project for my POCO classes and NHibernate mapping files. Change this to Silverlight1.Web or whatever assembly name where your mapping files were added.

One last plumbing task to complete. We need to implement the OperationContract so that Silverlight can call and fetch a list of musical instruments. I keep my web methods very thin but for illustration purposes only I'll just code it right there:

   1:  public class ConcertMusicService : IConcertMusicService
   2:  {
   3:      public IList<Instrument> GetInstruments()
   4:      {
   5:          IList<Instrument> list;
   6:          using (ISession session = NHibernateHelper.OpenSession())
   7:          {
   8:              IQuery query = session.CreateQuery("FROM Instrument");
   9:              list = query.List<Instrument>();
  10:          }
  11:          return list;    
  12:      }
  13:  }

Do not do this in a production application. Get that data access plumbing out of your web method and into a data layer somewhere. That makes it easy to write unit tests that call the data layer too. But this is fine for our purposes. Run your unit tests and make sure it's all working. Then wire up the Silverlight MainPage.xaml to consume the data. Drag a DataGrid onto your MainPage.xaml. It should register the System.Windows.Controls.Data assembly and stub out a DataGrid for you:

   1:  <data:DataGrid x:Name="InstrumentDataGrid" AutoGenerateColumns="False" Height="400" Width="200">
   2:      <data:DataGrid.Columns>
   3:          <data:DataGridTextColumn Header="ID" Binding="{Binding ID}" />
   4:          <data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
   5:      </data:DataGrid.Columns>
   6:  </data:DataGrid>

Create a service reference to the WCF service in your Silverlight app. Then in the code behind make an async call to the web service and bind the results to the grid:

   1:  public partial class MainPage : UserControl
   2:  {
   3:      public MainPage()
   4:      {
   5:          InitializeComponent();
   6:          Loaded += new RoutedEventHandler(MainPage_Loaded);
   7:      }
   8:   
   9:      void MainPage_Loaded(object sender, RoutedEventArgs e)
  10:      {
  11:          ConcertMusicServiceClient service = new ConcertMusicServiceClient();
  12:          service.GetInstrumentsCompleted += 
  13:              new EventHandler<GetInstrumentsCompletedEventArgs>(Service_GetInstrumentsCompleted);
  14:          service.GetInstrumentsAsync();
  15:      }
  16:   
  17:      void Service_GetInstrumentsCompleted(object sender, GetInstrumentsCompletedEventArgs e)
  18:      {
  19:          InstrumentDataGrid.ItemsSource = e.Result;  
  20:      } 
  21:  }

That's all there is to it.