Monday, January 16, 2012

Mapping-by-Code - inheritance

Next article in Ayende's NHibernate mapping series is about inheritance mappings. As we know, there are few different approaches to inheritance in database. Let's see how we can map it using NHibernate's 3.2 mapping-by-code.

Let's use the same model as Ayende did:

Single table

And let's begin with single table approach (table per hierarchy):

public class PartyMap : ClassMapping<Party>
{
public PartyMap()
{
Id(x => x.Id, i => i.Generator(Generators.HighLow));

Discriminator(x =>
{
x.Force(true);
x.Formula("arbitrary SQL expression");
x.Insert(true);
x.Length(12);
x.NotNullable(true);
x.Type(NHibernateUtil.String);

x.Column("discriminator");
// or...
x.Column(c =>
{
c.Name("discriminator");
// c.Length(21);
// c.NotNullable(false);
// etc.
});
});
}

public class CompanyMap : SubclassMapping<Company>
{
public CompanyMap()
{
DiscriminatorValue("Company");
Property(x => x.CompanyName);
}
}

public class PersonMap : SubclassMapping<Person>
{
public PersonMap()
{
DiscriminatorValue("Person");
Property(x => x.FirstName);
}
}
}

Single table inheritance mapping consists of two parts - discriminator mapping and subclasses mappings.

Discriminator column is mapped with Discriminator method. Mapping options offered by this method looks a bit messy. Length and NotNullable methods are available both in the Column method options (as in other mappings) and in the discriminator options directly. It looks like they are equivalent, what's called last "wins".

Mapping of subclasses is done through separate mapping classes that inherit from SubclassMapping<T>.

An important thing to remember when mapping inheritance using mapping-by-code is that when registering our mappings we should not look for ClassMapping<T> inheritors only - SubclassMapping<T> (and JoinedSubclassMapping<T> and UnionSubclassMapping<T>, mentioned later) do not inherit from ClassMapping<T>. The solution I'm using is to look for all implementations of IPropertyContainerMapper<T>.

Fluent NHibernate's equivalent for single table

Single table inheritance mapping is almost identical in Fluent NHibernate to mapping-by-code:

public class PartyMap : ClassMap<Party>
{
public PartyMap()
{
Id(x => x.Id).GeneratedBy.HiLo(maxLo: "100");

DiscriminateSubClassesOnColumn("discriminator")
.AlwaysSelectWithValue()
.Formula("arbitrary SQL expression")
.ReadOnly()
.Length(12)
.Not.Nullable()
.CustomType<string>();
}

public class CompanyMap : SubclassMap<Company>
{
public CompanyMap()
{
DiscriminatorValue("Company");
Map(x => x.CompanyName);
}
}

public class PersonMap : SubclassMap<Person>
{
public PersonMap()
{
DiscriminatorValue("Person");
Map(x => x.FirstName);
}
}
}

The way of defining subclasses is identical. The discriminator mapping differs in few names: Force is AlwaysSelectWithValue in FNH, Type is CustomType and Insert(false) can be mapped using ReadOnly. Moreover, the DiscriminateSubClassesOnColumn method, that is an entry point for discriminator mapping, requires specifying discriminator column name explicity - no default provided.

There are some more standard column-related methods available, analogously to mapping-by-code Column method options.

Table per class

The second strategy for mapping inheritance is table per class with joined subclasses. In this option subclasses are stored in separate tables that have foreign key to base class table and are joined with the table for base class, if needed. In this case, in mapping-by-code, we have to map subclasses by inheriting from JoinedSubclassMapping<T>. Here is the example of joined subclass mapping with all available options:

public class CompanyMap : JoinedSubclassMapping<Company>
{
public CompanyMap()
{
Key(k =>
{
k.Column("PartyId");
// or...
k.Column(c =>
{
c.Name("PartyId");
// etc.
});

k.ForeignKey("party_fk");
k.NotNullable(true);
k.OnDelete(OnDeleteAction.Cascade); // or OnDeleteAction.NoAction
k.PropertyRef(x => x.CompanyName);
k.Unique(true);
k.Update(true);
});

Property(x => x.CompanyName);
}
}

Fluent NHibernate's equivalent for table per class

In Fluent, subclasses are mapped by inheriting from the same SubclassMap<T> as in single table strategy. Only the method used differs - instead of DiscriminatorValue, we're using KeyColumn method with column name in the parameter (required, no default value). Looks like there's no way to configure other key column's options here.

public class CompanyMap : SubclassMap<Company>
{
public CompanyMap()
{
KeyColumn("PartyId");
Map(x => x.CompanyName);
}
}

Table per subclass

The third option is to use table per subclass with unioned subclasses. This time there is no separate table for base class, common columns are specified in each table for subclass separately and subclass tables share the same key generator. Mapping union subclasses with mapping-by-code is fairly simple - we just need to map the class by inheriting from UnionSubclassMapping<T> - no additional requirements or options.

public class CompanyMap : UnionSubclassMapping<Company>
{
public CompanyMap()
{
Property(x => x.CompanyName);
}
}

Fluent NHibernate's equivalent for table per subclass

Again, in Fluent, subclass maps inherit from the same SubclassMap<T>. To differentiate this strategy from the single table strategy, we have to include a call to UseUnionSubclassForInheritanceMapping method in the parent class mapping.

public class PartyMap : ClassMap<Party>
{
public PartyMap()
{
Id(x => x.Id).GeneratedBy.HiLo(maxLo: "100");
UseUnionSubclassForInheritanceMapping();
}

public class CompanyMap : SubclassMap<Company>
{
public CompanyMap()
{
Map(x => x.CompanyName);
}
}

public class PersonMap : SubclassMap<Person>
{
public PersonMap()
{
Map(x => x.FirstName);
}
}
}

Saturday, January 14, 2012

NullReferenceException in StructureMap after refactoring

I've encountered strange NullReferenceException in StructureMap when defining constructor arguments for the dependency after major refactoring and making previously abstract class non-abstract. Here is the code I had:

public interface IClass {}

public /*abstract*/ class Class : IClass
{
protected Class(string test) {}
}

public class TheRegistry : Registry
{
public TheRegistry()
{
For<IClass>().Use<Class>()
.Ctor<string>().Is("test");
}
}

And here's the stack trace of inner NullReferenceException:

   at StructureMap.Graph.Constructor.FindFirstConstructorArgumentOfType(Type type)
in c:\code\structuremap\Source\StructureMap\Graph\Constructor.cs:line 82
at StructureMap.Graph.Plugin.FindArgumentNameForType(Type type, CannotFindProperty cannotFind)
in c:\code\structuremap\Source\StructureMap\Graph\Plugin.cs:line 92
at StructureMap.Graph.Plugin.FindArgumentNameForType[T]()
in c:\code\structuremap\Source\StructureMap\Graph\Plugin.cs:line 77
at StructureMap.Pipeline.SmartInstance`1.getArgumentNameForType[CTORTYPE]()
in c:\code\structuremap\Source\StructureMap\Pipeline\SmartInstance.cs:line 226
at StructureMap.Pipeline.SmartInstance`1.Ctor[CTORTYPE]()
in c:\code\structuremap\Source\StructureMap\Pipeline\SmartInstance.cs:line 219
at NHManyToMany.TheRegistry..ctor()
in C:\Documents and Settings\Adam\Moje dokumenty\Projects\test\NHManyToMany\TheRegistry.cs:line 21

StructureMap can't find string-typed argument in the constructor. Most probably the exception like this will be thrown where there's no constructor with string argument. But in my case, there was one.

It took me some time to figure out what's wrong here - my constructor is protected, thus inaccessible for StructureMap. I forgot to change it into public after removing the abstract keyword. StructureMap obviously need to have an accessible constructor to work with, so the same issue may come out with internal constructors from other assemblies.

Friday, January 13, 2012

Mapping-by-Code - ManyToOne

Next up for inspection for mapping-by-code is the <many-to-one> element. It's mapping-by-code equivalent is ManyToOne. Here are its possible options:

ManyToOne(x => x.PropertyName, m =>
{
m.Column("column_name");
// or...
m.Column(c =>
{
c.Name("column_name");
// other standard column options
});

m.Class(typeof(ClassName));
m.Cascade(Cascade.All | Cascade.None | Cascade.Persist | Cascade.Remove);
m.Fetch(FetchKind.Join); // or FetchKind.Select
m.Update(true);
m.Insert(true);
m.Access(Accessor.Field);
m.Unique(true);
m.OptimisticLock(true);

m.Lazy(LazyRelation.Proxy);

//m.PropertyRef ???
//m.NotFound ???

m.ForeignKey("column_fk");
m.Formula("arbitrary SQL expression");
m.Index("column_idx");
m.NotNullable(true);
m.UniqueKey("column_uniq");
});

The first parameter (as almost always) is an lambda expression specifying mapped property in our entity. The second (as almost always) are the mapping options.

Column method (as almost always, again) is to specify database column that keeps the relation value. By default, its name is equal to property name, without any "_id" postfix or something. We can change its name only using the overload with string or we can customize all the options using the second overload. Its possibilities are shown in the post about property mapping - it generally works the same way, so I'll skip it here.

Cascade is used pretty often. Note that mapping-by-code redefined it a bit: save-update option is called Persist and delete is Remove here. This is configured using an flags-type enumerable, so it's easy to combine values. There's also an alternative syntax provided using extension methods:

    m.Cascade(Cascade.Persist.Include(Cascade.Remove));

By now, there's no way to map two features useful for legacy inconsistent databases - property-ref and not-found. Maybe Fabio decided that legacy databases wouldn't be mapped with new mappings?

Fluent NHibernate's equivalent

ManyToOne's equivalent in FNH is References:

References(x => x.PropertyName, "column_name")
.Class<ClassName>()
.Cascade.SaveUpdate()
.Fetch.Join()
.Update()
.Insert()
.ReadOnly()
.Access.Field()
.Unique()
.OptimisticLock()
.LazyLoad(Laziness.Proxy)
.PropertyRef(x => x.PropertyRef)
.NotFound.Ignore()
.ForeignKey("column_fk")
.Formula("arbitrary SQL expression")
.Index("column_idx")
.Not.Nullable()
.UniqueKey("column_uniq");

ReadOnly is just a FNH's shortcut for setting both .Not.Insert() and .Not.Update().

Wednesday, January 11, 2012

Mapping-by-Code - Component (and odd cases of Fluent NHibernate's fluency)

Let's move on with mapping-by-code vs. XML vs. Fluent NHibernate. The second post in Ayende's series was about <component> mapping. It's equivalent in mapping-by-code is Component, of course. There are total 6 overloads for Component method - 3 parametrized with lambda expression and 3 with strings for cases where the property is not publicly visible. In each three, there is an overload designed for dynamic components, which are separate topic. So the overloads that interest us have signatures like this:

public void Component<TComponent>(
Expression<Func<TEntity, TComponent>> property,
Action<IComponentMapper<TComponent>> mapping)
where TComponent : class

The first parameter is an lambda expression specifying the property of type TComponent. The second is the component mapping itself - it can contain component's properties mapping (and other class mapping parts except Id) and some options defining component's behavior.

Component(x => x.Address, c =>
{
// mappings for component's parts
c.Property(x => x.City);
c.Property(x => x.ZipCode);
// etc...

// mappings for component's options
c.Parent(x => x.Owner, p => p.Access(Accessor.ReadOnly));
c.Access(Accessor.Property); // or Accessor.Field or Accessor.ReadOnly
c.Class<TownHallAddress>();

c.Insert(true);
c.Update(true);
c.OptimisticLock(true);
c.Lazy(true);
});

Mapping for component's parts can of course contain its own options - i.e. see previous post for Property options.

Parent is a way to create bidirectional relationship between component and its owning entity - it allows mapping back to entity. The only thing that can be customized about this relationship is how should NHibernate access the Parent property in component class - using Access method. This needs to be distinguished from component's Access method, that affects how NHibernate access the opposite - component property in entity. Insert, Update, OptimisticLock and Lazy are about the latter property, too.

One thing is probably missing - both XML and Fluent mapping allows to add Unique constraint on the component, I can't see how to do it with mapping-by-code.

Fluent NHibernate's equivalent

One of the ways to map component in FNH is:

Component(x => x.Address, c =>
{
// mappings for component's parts
c.Map(x => x.City);
c.Map(x => x.ZipCode);
// etc...

// mappings for component's options
c.ParentReference(x => x.Owner)
.Access.ReadOnly()
.Insert()
.Update()
.OptimisticLock()
.LazyLoad()
.ReadOnly()
.Unique();

c.SqlUpdate("update query")
c.SqlInsert("insert query")
c.SqlDelete("delete query")
c.SqlDeleteAll("delete all query")
});

ReadOnly is just a FNH's shortcut for setting both .Not.Insert() and .Not.Update().

Note that Fluent NHibernate allows to specify raw SQL queries for updates, inserts and deletes - mapping-by-code doesn't. But this is not mapping-by-code's limitation, it's rather a FNH bug. Mapping raw queries doesn't make a sense for components, that are by definition owned and managed by its owning entity and NHibernate's XML schema doesn't even allow these attributes in component mapping.

Moreover, FNH's fluency introduces a lot of confusion in cases like this:

c.ParentReference(x => x.Owner).Access.ReadOnly();

It may look like defining an access strategy for parent reference, but no - it is defining an access strategy for the component itself and there's no way to set the former in Fluent NHibernate (at least I can't see any).

Note also that there are three alternative ways to attach component's options and all of it seems to work the same:

Component(x => x.Address, c =>
{
c.LazyLoad().ParentReference(x => x.Owner);
c.ParentReference(x => x.Owner);
})
.ParentReference(x => x.Owner);

And - continuing the exploration of Fluent's API odd cases - setting access strategy and disabling the component from update and insert queries looks like that:

c.Access.ReadOnly().ReadOnly();

Well, now I clearly see the limitations of fluent interfaces. In Fluent NHibernate it can sometimes be more confusing than helpful. Mapping-by-code seems to have much more elegant solution here.

Monday, January 9, 2012

Mapping-by-Code - Property

I am spending quite a lot of time recently with NHibernate 3.2 mapping-by-code feature and as I've already mentioned, my most serious obstacle with this evaluation is that there is virtually no resources on the net. If these answers are everything the Web has to offer, there's a lot of space for improvement.

I am planning to prepare a series of posts covering the most important NHibernate's mapping features implemented using mapping-by-code. I'll probably follow Ayende's great series about XML mappings, at least in terms of ordering. I'm not going to describe the features itself, I'll rather focus on mapping interface. For features description - refer to Ayende's posts.

So let's start with <property>. Its equivalent in mapping-by-code is... Property - isn't it surprising? Well, in Fluent NHibernate it is called Map. There's no rocket science here and everything is pretty simple.

Property(x => x.Property, m =>
{
m.Column("columnName");
// or
m.Column(c =>
{
c.Name("columnName");
c.Default("defaultValue");

c.SqlType("varchar(max)");
c.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1);

c.NotNullable(true);
c.Check("len(columnName) > 1");
c.Precision(2);
c.Scale(2);
c.Index("column_idx");
c.Unique(true);
c.UniqueKey("column_uniq");
});

m.Type<string>(); // or IUserType
m.Update(true);
m.Insert(true);
m.Formula("arbitrary SQL expression");

m.Access(Accessor.Field); // or Accessor.Property or Accessor.NoSetter
// or
m.Access(typeof(CustomAccessor));

m.OptimisticLock(false);
m.Generated(PropertyGeneration.Insert); // or PropertyGeneration.Always or PropertyGeneration.Never

m.Lazy(true);
});

Mapped property goes as lambda expression (or string property name, if it is hidden) in first parameter and this is the only obligatory element - everything else has its defaults and can be skipped (and most often, it should). All the other attributes from the XML have its corresponding method in configuration object in second parameter.

One thing to note is that column can be configured using Column method either with simple string (when customising only name) or with column configuration, that allows to set different DDL-level column properties. Not every feature is implemented in every provider and not every feature makes sense for every column type obviously - i.e. Precision and Scale are for numerics only.

Side note: In the example above I'm specifying SqlType explicitly to varchar(max), but this line

Property(x => x.Name, m => m.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1));

will also produce varchar(max) in SQL Server, and that solution seems to be nicer.

Fluent NHibernate's equivalent

Map(x => x.Property, "columnName")
.Default("defaultValue")
.CustomSqlType("varchar(max)")
.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1)
.Not.Nullable()
.Check("len(columnName) > 1")
.Precision(2)
.Scale(2)
.Index("column_idx")
.Unique()
.UniqueKey("column_uniq")
.CustomType<string>()
.Update()
.Insert()
.Formula("arbitrary SQL expression")
.Access.Field()
// or .Access.Using<CustomAccessor>()
.OptimisticLock()
.Generated.Insert()
.LazyLoad()
.ReadOnly();

The only difference apart from different naming for some properties and Property vs. Map name itself is the ReadOnly method available in FNH. It is just a shortcut for setting both .Not.Insert() and .Not.Update().

Friday, January 6, 2012

Mapping-by-Code naming convention resembling Fluent

Recently I've posted about my first impressions about NHibernate's mapping-by-code and the one thing I was surprised was that the default naming conventions provided are not usable.

I was using default Fluent NHibernate's naming convention for quite a long time and there were only few scenarios (not counting legacy databases) when I needed to specify columns or table names on my own. With mapping-by-code it is not possible to map simple many-to-many without changing the default naming convention or specifying the names in the mapping, quite XML-style. A bit annoying.

So, as a part of my experiments with the tool, I've written another naming convention that is aimed to resemble Fluent NHibernate's default naming convention, so that:

  • foreign key columns in child-parent relationships are called "Parent_id"
  • many-to-many intermediate table is called "FirstToSecond" and its foreign key columns are "First_id" and "Second_id"
  • on bidirectional relations, both sides match together automatically

Nothing really impressing, but missing in default mapping-by-code naming convention.

The code is here on GitHub. Feel free to use it if you find it useful. It is of course far from being complete - it's not even trying to cope with features like maps, one-to-one's, any's, many-to-any's etc.

My convention doesn't support join either and it seems that it is not possible with current mapping-by-code implementation - there's no event to attach to in case of join mapping and it looks like joins are implemented in different way. Foreign key column of joined table is called "parent_key", and can be overriden in ClassMapping only.

I'm inheriting ConventionModelMapper behaviors and adding few own rules, that are applied before mapping, so that it can be overriden in ClassMappings in a standard way. I've used few extension methods provided by NHibernate's code. It's a pity that they are not mentioned anywhere - I've just found it in the source code quite accidentally.

When using my ModelMapperWithNamingConventions in place of ModelMapper or ConventionModelMapper, many-to-many verbose mapping I've presented previously is reduced to something more friendly and quite elegant, like Fluent NHibernate has accustomed me - I can remove key column definitions from both Bag and ManyToMany mapping and remove Table name definition from Bag mapping.

public class Street
{
public Street()
{
Districts = new List<District>();
}

public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual ICollection<District> Districts { get; set; }
}

public class StreetMap : ClassMapping<Street>
{
public StreetMap()
{
Id(x => x.Id, m => m.Generator(Generators.Identity));
Property(x => x.Name, m => m.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1));

Bag(x => x.Districts, c =>
{
c.Key(k => k.NotNullable(true));
c.Cascade(Cascade.All);
c.Inverse(true);
}, r => r.ManyToMany());
}
}

And here are the tables generated by Hbm2dll tool:

Wednesday, January 4, 2012

NHibernate's Mapping by Code - first impressions

Recently I've found some time to check out NHibernate's 3.2 new mapping-by-code feature that allows to completely remove XML mappings from NHibernate's pipeline.

I'm pretty used to using Fluent NHibernate, but I always think of it as the only alternative to plain hbm.xml mappings, that are just too clumsy and too verbose. I like FNH's fluency and clarity, but I think it's far from being ideal solution. My two major objections are that it hides some very important mapping parts like collection types in defaults and it introduces confusion by renaming some NHibernate's concepts without clear reason (i.e. <property> renamed in FNH to Map(), being totally different from original NHibernate's <map>).

I like the idea of integrated code-first mapping solution in NHibernate to replace FNH pretty much for several reasons:

  • there will be no additional library on which our projects depends;
  • there will be no mismatch between assemblies versions and no additional obstacle for upgrading NH; see often discussed workarounds for the lack of Fluent NH package compatible with NH 3.2 on NuGet (there is already the compatible package, but it's not marked as the latest one, surprisingly);
  • the set of features offered by integrated mapping solution will match NHibernate's core features more likely, along with naming conceptions;
  • last but not least, we'll save on XML transformations that is still done by Fluent NHibernate, as native mapping-by-code skips this step completely.

I've took the conformist, class-by-class approach as I feel it's better for complicated models. I was using Fluent NHibernate's automapping, but it often turned out that almost all entities needed some overrides and this reduces the sense for automapping at all. Moreover, I like being explicit about such an important things like database interactions. Each mapping change should trigger careful testing as mappings are quite fragile part of the application. When mapping changes implicitly together with class structure changes because of some kind of automapping or detailed conventions, the impact of such change can be easily overlooked.

The simple mappings are... simple. For anyone using either XML mappings or Fluent NHibernate, there should be no problem to write class maps. One-to-many relationship looks like this:

public class City
{
public virtual int Id { get; protected set; }
public virtual long Population { get; set; }
public virtual string Name { get; set; }
public virtual Municipality Municipality { get; set; }
}

public class CityMap : ClassMapping<City>
{
public CityMap()
{
Id(x => x.Id, m => m.Generator(Generators.Identity));
Property(x => x.Population);
Property(x => x.Name, m => m.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1));
ManyToOne(x => x.Municipality, m =>
{
m.Cascade(Cascade.All);
m.NotNullable(true);
});
}
}

I've encountered first problems when tried to map many-to-many. It seems like mapping-by-code doesn't come with any useful default naming convention for tables and columns and we need to specify it explicitly in mapping - it looks more like XML in this case. Fluent NH can figure out pretty decent names on its own. I'll probably need to define some conventions to make it resemble Fluent mapping more. Here is what I had to do to make it work (I'm showing one side of the relationship only, but you can see the thing):

public class Street
{
public Street()
{
Districts = new List<District>();
}

public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual ICollection<District> Districts { get; set; }
}

public class StreetMap : ClassMapping<Street>
{
public StreetMap()
{
Id(x => x.Id, m => m.Generator(Generators.Identity));
Property(x => x.Name, m => m.Length(SqlClientDriver.MaxSizeForLengthLimitedString + 1));

Bag(x => x.Districts, c =>
{
c.Key(k =>
{
k.Column("StreetId");
k.NotNullable(true);
});
c.Cascade(Cascade.All);
c.Table("Streets2Districts");
c.Inverse(true);
}, r => r.ManyToMany(m => m.Column("DistrictId")));
}
}

Now I'm trying to figure out how to map dynamic components, but it's not as easy as it should be. Here is the API I'm trying to use:

public void Component<TComponent>(
Expression<Func<TEntity, IDictionary>> property,
TComponent dynamicComponentTemplate,
Action<IDynamicComponentMapper<TComponent>> mapping)
where TComponent : class

or

protected virtual void RegisterDynamicComponentMapping<TComponent>(
Expression<Func<TEntity, IDictionary>> property,
Action<IDynamicComponentMapper<TComponent>> mapping)
where TComponent : class

Anyway, I don't know what TComponent in case of dynamic components should be. Resources on the web are extremely poor - the only answer I've found was not really helpful.

And here is the main weakness of mapping-by-code for me by now - it's too fresh. There is virtually no documentation apart from a few examples mentioned at StackOverflow. And even the code from initial Fabio Maulo's blog posts introducing the feature are outdated as some things changed before it goes to the production.

It's hard to think about migrating from FNH to mapping-by-code if it is still such an unknown land. Anyway, I think the direction is very good and the beginning is promising. I'll probably try to explore this land on my own.