Database – NHibernate and complex domain model against a legacy database

databasedomain-driven-designdomain-modelnhibernateorm

I'm trying to refactor (actually, rewrite) an application which currently uses only stored procedures to access the database (hundreds of SPs). My goal is to use Nhibernate and follow a good design as much as possible.
But since the database (and the SPs) are used by dozens of other apps, I can't really change the db design. And off course, it's awful.

I'm facing a design problem and I can't really find a good solution.
I have a table called movies which contains movies, but these movies can be different "things". For example, this table contains movies as well as episodes of tv shows and the only way to know the difference is a field named "episode" which is set to 0 for movies and 1 for episodes.

My objective is to expose the following class hierarchy :

public abstract class Program {}
public class Episode : Program {}
public class Movie : Program {}

Currently, I have mapped the whole movies table to a model class MoviesModel and then I build my Episode/Movie class through AutoMapper and a factory method in the Program class :

public static Program Load(MoviesModel movieModel)
    {
        if (movieModel.Episode > 0)
            return Mapper.Map<Episode>(movieModel);
        return Mapper.Map<Movie>(movieModel);
    }

This seems really wrong on many levels : I have an anemic data model since my MoviesModel is totally empty of any business logic, the automapper stuff becomes really hard to maintain when I add many other entities with relations to Movies, and I break the lazy loading with AutoMapper.

I heard about the any mapping of nhibernate but it doesn't really solve my issue, it just creates sub components of a class.

So my questions are :

  • Ideally, where should be my business logic ? I guess in the MoviesModel class but I don't really like the idea to expose my database fields.
  • Is there a way with nhibernate to map the same table in different classes based on a field value ?
  • Is there a point to wrap the nhibernate objects if I want to provide a "clean" public API ?

My goal is to build a base library which will be used (hopefully) on other legacy apps so I want to provide a clean API with logical methods and without exposing the database mess even if I still have to deal with it.

Thanks for any help to put me in the right direction.

Best Answer

Unfortunately I don't know much about AutoMapper but I can offer a solution to your second question. Fluent NHibernate is a tool to aide with your NHibernate mappings, allowing you to configure them in a programmatic way rather using than XML. One of the methods you can call when setting up your mappings is DiscriminateSubClassesOnColumn() which allows you to specify the database column that will be used to create your sub-classes. Then in your sub-classes you specify the DiscriminatorValue which can be an enum.

Here is what I imagine your mappings to look like (untested code):

public class ProgramMap : ClassMap<Program>
{
    public ProgramMap()
    {
        //map your fields as normal, eg: Map(p => p.Id), Map(p => p.Name)
        DiscriminateSubClassesOnColumn<int>("Episode");
    }
}

public class MovieeMap : SubclassMap<Movie>
{
    public MovieMap()
    {
        DiscriminatorValue(0);
    }
}

The problem may actually be specifying the DiscriminatorValue for your Movies but hopefully this gives you something to go on. For reference I've used the following links to put this answer together so they may be worth a look in case I've missed something out.

Note that if you don't specify the DiscriminatorValue, Fluent NHibernate assumes that the discriminator column contains your class name (which would be a terrible database design!).