Broloco

(or Using NHibernate and WCF)

Introduction

If you have a Domain Model, and a rich-client (e.g, WinForms/WPF), you might want to expose your application's functionality across a Service Layer/ Remote Facade. Your Service Layer will need to return objects containing domain information, and I prefer to re-use my Domain Model classes directly, rather than invent unnecessary DTO objects (DRY).

Typically your Domain Model might be entities mapped to a relational database using NHibernate (or some other ORM), and a Service Layer exposed using WCF (or some other remoting technology).

This should be simple, however there are a few issues you might run into.

Lazy Load

Most good ORM solutions will use Lazy Load to allow the domain objects to access each other using their associations while silently taking care of the data-access concern.

When you come to serialise an object that came from a connected Domain Model you now have a problem. With Lazy Load it's like pulling a loose thread that could potentially load up the entire object model into memory. You need a way to indicate the 'section' of the object graph that you want.

Lazy Load is also often implemented using interception, which in turn usually means that the object might actually be a generated proxy. Some remoting technologies do not play well with auto-generated classes; you might need to transform them back to their 'real' class to send them across the wire.

(WCF can generate a System.ServiceModel.CommunicationException: ... Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer)

In addition, the serialisation of the objects often occurs after the service call is complete. If the database connection is already closed then you may be unable to Lazy Load more of the domain.

(NHibernate can generate a NHibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed)

Domain Object Graph Depth

Some ORM solutions allow you to 'disconnect' a portion of the object graph to prevent Lazy Load issues, but then you have to handle two further issues:

1. Loaded Graph is Too Deep ...

During a single service call the domain objects might load a deep graph to solve a given problem, and then return a single object as its result. In this case the loaded object graph might be much larger than you want to send across the wire. (Either for performance reasons, or security reasons perhaps.)

2. Loaded Graph is Too Shallow ...

Other times the graph will only be partially loaded, and you want to return a result from a service call that loads deeper information. For example, a call GetPersonDetail() might need the Person object, and it's parents, children, addresses, ... or specifically exclude some personal details. In addition, you need to be careful not to fall into the select N+1 problem while fetching all the objects you want.

In both of these cases you again need to indicate the portion of the object graph that needs to be sent across the wire.

Cyclic Object Graphs

Most connected Domain Models are full of cyclic references, with bi-direction associations between objects being common. A typical object-graph for these classes:

public class Person
{
    // 1:m association between Person and Child
    public IList<Child> Children;
    ...

public class Child
{
    // m:1 association (back pointer)
    public Person Parent;
    ...
        

... might look like this in memory:

However, if you're going to try exposing your services using SOAP you're going to find out that cyclic graphs like this are not allowed. (I can only assume the guys that defined SOAP (WS-I) were asleep the day they decided that no-one would need to send cyclic graphs across the wire.)

To send this across the wire you might need to transform the above graph into something like this:

Solving Using a Graph Utility Class

My preferred option for sorting these problems is to use a utility class that allows you to quickly specify a graph of objects to 'copy'.

With a sprinkling of Lambda Expressions and extension methods you can have code that looks like something like this:

// Copies a person, its children (with its parent),
// and the grandchildren.
Person personCopyToReturnAcrossWcf =
    myRootPersonObject
        .Graph()
        .Add(p => p.Children, new Graph<Child>()
            .Add(c => c.Parent))
            .Add(c => c.Granchildren))
        .Copy();
        

The source for the utility class can be found here: link

Finally

Some people dislike the idea of sending the 'real' domain objects across the wire. Instead they create DTO objects for everything that has to be passed back from a service.

My personal preference is to only create DTO classes when they are needed, hopefully saving time on creating both the DTO objects and the code to map my domain properties to them. Reporting is an example where this usually breaks down and I find myself creating DTO classes to send information to a client.

Utimately, whether you use graphing, or use DTOs, you still have to be aware of all of the above issues when using a Domain Model and a Service Layer/Remote Facade.

Submit this story to DotNetKicks Shout it

I'm a big fan of NHibernate, and also of its Query Object the ICriteria API. I don't much care for 'magic strings' in my code though.

LINQ provides a way to strongly type your queries, but there are still times when you want an opaque query language with an object-oriented interface.

With .Net 3.5 came Lambda Expressions, which allow you to strongly type the individual expressions in a query. I started writing some extension methods to allow me to use lambda expressions with ICriteria, so code like:

mySession
    .CreateCriteria(typeof(Person))
        .Add(Expression.Eq("Name", "smith"))
        .List<Person>();
        

... turns into code like:

mySession
    .CreateCriteria(typeof(Person))
        .Add<Person>(p => p.Name == "smith")
        .List<Person>();
        

There turned out to be quite a few extension methods to write to cover all the different combinations of ICriteria that can be written (including DetachedCriteria, aliases, subqueries, ...) I've packaged it into a project on Google Code for anyone who wants to use it:

Submit this story to DotNetKicks Shout it

An Alternative to CodeSmith

I'm a big fan of code-generation for automating boiler-plate code. I used to use CodeSmith for this, but the freeware version is no longer maintained. T4 is my new favourite tool for code generation, and there's a wealth of information available on using it on Oleg Sych's site.

Passing Command-Line Parameters to TextTransform

The tools come with a command-line host for T4 (TextTransform.exe), but there's no obvious way to pass parameters to the templates.

You can pass parameters using the command-line option -a:

TextTransform.exe
    -a mappingFile!c:\myPath\MyClass.hbm.xml
    -out c:\myGeneratedFiles\MyClass_Generated.cs
    c:\myTemplates\GenerateNHibernateProperties.tt
        

In order to retrieve the parameter from inside the template, you can use a little reflection:

private string GetCommandLineProperty(string propertyName)
{
    PropertyInfo parametersProperty =
        Host
            .GetType()
            .GetProperty("Parameters",
                BindingFlags.NonPublic | BindingFlags.Instance);

    StringCollection parameters =
        (StringCollection)parametersProperty
            .GetValue(Host, null);

    foreach (string parameter in parameters)
    {
        string[] values = parameter.Split('!');
        int length = values.Length;
        if (values[length - 2] == propertyName)
            return values[length - 1];
    }
    return null;
}
        

Replacing NHibernate Magic Strings

Now I can loop through my .hbm.xml files in my build, generating the 'magic strings' for the properties of each class (example template and project is linked below).

This turns code like:

IList<Media> mediaWithNameAndType =
 DomainRegistry.Repository
  .CreateQuery<Media>()
  .Add(Expression.Eq("OwningLibrary", this))
  .Add(Expression.Eq("Type", media.Type))
  .Add(Expression.Eq("Name", media.Name))
  .List<Media>();
        

Into code like:

IList<Media> mediaWithNameAndType =
 DomainRegistry.Repository
  .CreateQuery<Media>()
  .Add(Expression.Eq(Media.Properties.OwningLibrary, this))
  .Add(Expression.Eq(Media.Properties.Type, media.Type))
  .Add(Expression.Eq(Media.Properties.Name, media.Name))
  .List<Media>();
        

Some links:

Submit this story to DotNetKicks Shout it

Introduction

In a previous post I demonstrated testing a Compact Framework application using Passive View. I also mentioned that I would use the same technique to test the presentation layer on other platforms. So to put that to the test I migrated that simple application to Silverlight.

Testing Platform

There are many more testing options for Silverlight than there are for the Compact Framework. If you're using the IDE, you might consider reading this for some of your options.

I chose to test my POCO controller classes inside the regular .Net framework using NUnit.

Instead of retargeting, I cross-compiled the controller class to the 'real' .Net framework. The view controls in Silverlight are a subset of the complete WPF controls, so they can be substituted in the test environment to simulate the runtime controls.

The only slight hindrance I came across was that when you attempt to use the WPF controls in NUnit you get the exception "InvalidOperationException : The calling thread must be STA". The controls insist on running on an STA thread, which requires a .config file for the test assembly containing the following:

<NUnit>
    <TestRunner>
        <add key="ApartmentState" value="STA" />
    </TestRunner>
</NUnit>
        

Passive View

As previously, the view is completely dumb. It contains no logic, just the controls that will be manipulated by the controller. The XAML is kept simple with mostly positioning logic.

<StackPanel x:Name="LayoutRoot"
    Background="White">

<TextBlock>
    Demonstration of Passive View to test
        Silverlight client
</TextBlock>

<Button x:Name="ShowMessage"
    Content="Show Message"
    Width="150"  Margin="20"/>
...
        

I exposed the controls as public fields on the View class. These were populated in the 'Loaded' event (note, this only fires in the Silverlight runtime - not the tests), then the controller was wired up:

public class MainView : UserControl
{

  public Button ShowMessage;
  public TextBlock Message;
  ...

  public MainView()
  {
    Loaded +=
      new RoutedEventHandler(UserControl_Loaded);
  }

  private void UserControl_Loaded(object sender,
      RoutedEventArgs e)
  {
    ShowMessage = (Button)FindName("ShowMessage");
    Message = (TextBlock)FindName("Message");
    ...
    new MainController(this);
    ...
        

During the tests a testable view class simply populates the fields with 'empty' controls allowing the controller logic to be tested, without requiring a full presentation runtime.

public class TestableView : MainView
{
  public TestableView()
  {
    ShowMessage = new Button();
    Message = new TextBlock();
    ...
    new MainController(this);
    ...
        

Migration from Windows Forms

The only remaining task was to migrate the namespaces to WPF from Windows Forms. Mostly this was just a search/replace exercise (with the compiler telling me everywhere something had changed):

  • Namespace moved to System.Windows;
  • Enabled property is now IsEnabled property;
  • MessageBox.Show has slightly fewer options;
  • Setting colours now uses a Brush class;
  • etc., ...

With just a little more work, you could wrap each control in a common interface (e.g., IButton, IComboBox), then the same controller could be used to run a view on multiple platforms (Silverlight/WPF/Windows Forms). You might even be able to use the controller to run a web application using a framework like Visual WebGui (which makes coding a web application magically like coding a Windows Forms application).

For a larger application I would definitely do this extra work - it is bound to pay itself back at some point, not least of all because you could have stubbed control implementations in the tests instead of the 'real' ones.

Summary

The modifications to move the demo from Windows Forms to Silverlight were a rewriting of the View (inevitable), and some minor syntax changes in the controller.

On a larger application the ability to keep 90% of your code (and the tests!) when migrating to another platform is invaluable, and Passive View is the best way I've seen of writing (and testing) the presentation layer.


Silverlight Passive View Demo
download, unzip, run CommandPrompt.bat, and type 'NAnt'

View Silverlight Passive View Demo Online

Submit this story to DotNetKicks Shout it

Following Richard's "HTML is crap" post this got me thinking about the real underlying message of his post. Yes technology has moved on a lot in recent years to the point where old reasons for choosing those [HTML applications] types of application have largely gone. However this isn't the first or the last time software people will have this frustration and here's why: too many business people come with software solutions and not business problems! I've no idea why this has happened other than some mistaken idea that software is easy and business is hard. In my experience when customers bring me software solutions rather than business problems the final software solutions I'm able to deliver to them are invariably poorer than they should be. So the next question is how can we stop people bringing us their half-baked solutions...

Submit this story to DotNetKicks Shout it