Tuesday, February 28, 2012

Loquacious XML builder

Let's try to make use of loquacious interface patterns I've shown in the previous post to build something simple but useful - an API to construct an arbitrary XML document with simple, readable and elegant piece of C# code. If you find it helpful, fell free to use it - for convenience, I've put it on GitHub.

We'll start with an utility class wrapping the standard cumbersome XML API. Nothing really interesting here, just few methods to add attributes, nested elements or inner content to a given XmlNode object.

internal class NodeBuilder
{
private readonly XmlDocument _doc;
private readonly XmlNode _node;

public NodeBuilder(XmlDocument doc, XmlNode node)
{
_doc = doc;
_node = node;
}

public void SetAttribute(string name, string value)
{
var attribute = _doc.CreateAttribute(name);
attribute.Value = value;
_node.Attributes.Append(attribute);
}

public XmlNode AddNode(string name)
{
var newNode = _doc.CreateElement(name);
_node.AppendChild(newNode);
return newNode;
}

public void AddContent(string content)
{
_node.AppendChild(_doc.CreateTextNode(content));
}
}

Now we'll create an entry point for our loquacious XML API - it'll be a static method that creates an instance of XmlDocument, uses NodeBuilder to initialize the document with a root element, runs a loquacious Action<INode> for the root node and finally, returns the XmlDocument content as a string.

public static class Xml
{
public static string Node(string name, Action<INode> action)
{
using (var stringWriter = new StringWriter())
{
var doc = new XmlDocument();
var root = new NodeBuilder(doc, doc).AddNode(name);
action(new NodeImpl(doc, root));

doc.WriteTo(new XmlTextWriter(stringWriter));
return stringWriter.ToString();
}
}
}

What do we need in the INode interface, used within Action<T> parameter? As always with loquacious interfaces, it should resemble one level of our object structure - an XML node in this case. So we'll have two simple methods to add an attribute and an inner content and another Action<INode>-parametrized method to add a new node at the next level in the XML structure.

public interface INode
{
void Attr(string name, string value);
void Node(string name, Action<INode> action);
void Content(string content);
}

The implementation of INode interface is pretty straightforward, following the patterns I've described previously.

internal class NodeImpl : INode
{
private readonly XmlDocument _doc;
private readonly NodeBuilder _nb;

public NodeImpl(XmlDocument doc, XmlNode node, string name)
{
_doc = doc;
_nb = new NodeBuilder(doc, node, name);
}

public void Attr(string name, string value)
{
_nb.SetAttribute(name, value);
}

public void Node(string name, Action<INode> action)
{
action(new NodeImpl(_doc, _nb.AddNode(name)));
}

public void Content(string content)
{
_nb.AddContent(content);
}
}

And that's it! We can use this three-class implementation to create any XML we need. For example, here is the code that builds a simple NuGet package manifest:

var package = Xml.Node("package", x => x.Node("metadata", m =>
{
m.Attr("xmlns", "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd");
m.Node("id", id => id.Content("Foo.Bar"));
m.Node("version", version => version.Content("1.2.3"));
m.Node("authors", authors => authors.Content("NOtherDev"));
m.Node("description", desc => desc.Content("An example"));
m.Node("dependencies", deps =>
{
deps.Node("dependency", d =>
{
d.Attr("id", "First.Dependency");
d.Attr("version", "3.2.1");
});
deps.Node("dependency", d =>
{
d.Attr("id", "Another.Dependency");
d.Attr("version", "3.2.1");
});
});
}));

Of course this is the simple case - we could construct XML like this using StringBuilder pretty easily, too. But the flexibility this kind of API gives is very convenient for more complex scenarios. I'm going to show something more complicated next time.

Thursday, February 23, 2012

On loquacious interfaces, again

I've recently finished my review of NHibernate's mapping-by-code feature and the thing I'm most impressed with is its API design. Fabio Maulo, mapping-by-code creator, calls this a loquacious interface, as opposed to chained, fluent interface. I don't know if that name is well established or formalized yet - Google shows only NH-related hits. I don't know any other projects using solely this kind of API either. But I think this is going to change soon, as Fabio's approach seems to be more powerful and in a lot of cases more readable and "fluent" than chained interfaces.

What exactly I'm talking about?

I'm thinking of an API intended to build complex structures in code that resembles the structure itself. Mapping-by-code API (loosely) resembles NHibernate's HBM XML structure, so that when in XML we had an attribute, in loquacious interface we have a method call, and when we had a nested element, we have a nested lambda expression.

<!-- HBM XML fragment -->
<property name="Example" lazy="false">
<column name="ColumnName" />
</property>
// mapping-by-code fragment
Property(x => x.Example, m =>
{
m.Lazy(false); // attribute equivalent
m.Column(c => c.Name("ColumnName")); // nested element equivalent
});

The first and most important thing to note is that loquacious interfaces supports tree structures, contrary to fluent chains, which are linear in its nature. As Martin Fowler mentions, fluent chains are "designed to be readable and to flow". Loquacious interface flows less, giving an ability to define arbitrarily complex structures insted, without losing on readability.

The only loss I can see (apart from less code needed to implement the API) is that there's no ability to enforce how many times and in what order methods are called - in the chain we can control it with types returned from each chain element, in loquacious interface's lambdas we have no control over how the methods are called.

How is it build?

What delights me is that there's no rocket science in loquacious interfaces at all (opposed to fluent chains which are hard to be designed well - see Fowler's article or my thoughts on Fluent NHibernate's component mapping). As we've seen in mapping-by-code example above, we have two types of methods inside lambdas in loquacious API - taking either simple object or another lambda. Methods with simple object-typed parameter are to modify the current level of structure we're creating, methods with lambda-typed parameter start a new level.

Suppose we want to use loquacious API to create a simple object tree like this:

var building = new Building()
{
Address = "1 Example Street",
Floors = new[]
{
new Floor()
{
Rooms = new[]
{
new Room() { Area = 33.0 },
new Room() { Area = 44.0 }
}
},
new Floor()
{
Rooms = new[]
{
new Room() { Area = 20.0 },
new Room() { Area = 30.0 },
new Room() { Area = 40.0 },
}
},
},
Roof = new Roof() { Type = RoofType.GableRoof }
};

To start building our Building, we have to create its first level using a method having Action<T>-typed parameter (Action<T> is a generic delegate taking single T parameter with no return value). T generic type should allow setting up elements available at given level - Address, Floors and Roof in this case. Let's sketch the starting point method's signature and prepare the interface used within its parameter:

public Building Building(Action<IBuildingCreator> action) { }

public interface IBuildingCreator
{
void Address(string address);
void Floor(Action<IFloorCreator> action);
void Roof(Action<IRoofCreator> action);
}

Address represents a simple Building's property, so it just has a string parameter. Floor and Roof represents complex objects, so we have another Action<T> parameters there. Methods have no return values - no chaining, standalone calls only.

Let's now implement our starting point method:

public Building Building(Action<IBuildingCreator> action)
{
var creator = new BuildingCreator();
action(creator);
return creator.TheBuilding;
}

We're instantiating an IBuildingCreator implementation and passing it to the action provided by our API user as lambda expression. IBuildingCreator's implementation creates a Building instance and exposes it through TheBuilding property. Each IBuildingCreator's method called by the user is supposed to modify that instance. Let's see the implementation:

internal class BuildingCreator : IBuildingCreator
{
private readonly Building _building = new Building();

public void Address(string address)
{
_building.Address = address;
}

public void Floor(Action<IFloorCreator> action)
{
var creator = new FloorCreator();
action(creator);
_building.Floors.Add(creator.TheFloor);
}

public void Roof(Action<IRoofCreator> action)
{
var creator = new RoofCreator();
action(creator);
_building.Roof = creator.TheRoof;
}

public Building TheBuilding { get { return _building; } }
}

The Building instance is created on BuildingCreator instatiation and modified by its members. Address method just sets up Building's property. Floor method repeats already known pattern - it creates the FloorCreator and appends newly built Floor to Floors collection. Roof method uses the same pattern again to assign Building's Roof property.

Note that we don't distinguish whether we're adding the element to a collection (like Floors) or we're assigning a single value (like Roof) at API level - it should be known from the semantics. Also note that the BuildingCreator class is internal and TheBuilding property is not included in the IBuldingCreator interface, so it stays our private implementation detail and don't need to be a part of public API we're creating - and that's quite neat.

Here's how to use the API we've just designed:

var building = Building(b =>
{
b.Address("1 Example Street");
b.Floor(f =>
{
f.Room(r => r.Area(33.0));
f.Room(r => r.Area(44.0));
});
b.Floor(f =>
{
f.Room(r => r.Area(20.0));
f.Room(r => r.Area(30.0));
f.Room(r => r.Area(40.0));
});
b.Roof(r => r.Type(RoofType.GableRoof));
});

The source code for this example is available on GitHub.

By following that pattern we can build an arbitrarily complex structures - we're not limited by the API design and its implementation will stay very simple - no method will exceed 3 lines of code. We can add new properties and levels easily, without breaking the API. Moreover, we have strongly typed lambdas everywhere, so our API can expose only methods that are valid at given point (not so easy with complex fluent chains). What's more, if we have recurring object patterns in different parts of our structure, we can reuse the same IXyzCreator interfaces and its implementations without any cost at all (again, try to do it within fluent chains).

Well, I'm quite impressed how many advantages this simple idea brings for us. I'm going to stick to that topic for a while to show some usages and "real" implementations of loquacious interfaces. Hope you'll enjoy!

Tuesday, February 21, 2012

Json.NET deserialization and initialization in constructors

I've recently run into a quite interesting problem when using Json.NET library. It shows up with a static lookup collection being modified during the deserialization of some objects. Although the behavior I've encountered is documented, but for me it is breaking a principle of least astonishment a bit, so I've decided to share.

I have a class, TestClass, that I'm going to serialize and deserialize using Json.NET. It contains a simple collection of string values, that is initialized in the constructor to contain some predefined values - it's is default state. I have these values defined somewhere in the separate class in a collection marked as readonly, treated like a constant, not supposed to be modified.

Here are the tests (written in Machine.Specifications) that illustrates the issue. I'm setting TestClass state in the constructor, but I expect it to be overwritten during the deserialization, as my JSON string contains different data. In fact, deserialized values are appended to the existing collection, which occurs to be exactly the same collection as my "constants".

public static class Constants
{
public static readonly IList<string> NotSupposedToBeModified = new List<string>()
{
"the first",
"the last"
};
}

public class TestClass
{
public IEnumerable<string> TheCollection { get; set; }

public TestClass()
{
TheCollection = Constants.NotSupposedToBeModified;
}
}

public class DeserializingTest
{
Because of = () =>
result = JsonConvert.DeserializeObject<TestClass>(@"{""TheCollection"":[""other""]}");

It should_deserialize_the_collection_correctly = () =>
result.TheCollection.ShouldContainOnly("other");

It should_not_modify_the_constant_collection = () =>
Constants.NotSupposedToBeModified.ShouldContainOnly("the first", "the last");

static TestClass result;
}

What is the result? Both tests failed:

should deserialize the collection correctly : Failed
Should contain only: { "other" }
entire list: { "the first", "the last", "other" }

should not modify the constant collection : Failed
Should contain only: { "the first", "the last" }
entire list: { "the first", "the last", "other" }

There are three separate issues that showed up together and resulted that apparently surprising behavior:

The first one is about the constant collection defined in Constants class, being not really constant. The readonly keyword guarantees that one can not replace the collection instance, but that already-created collection instance itself still can be modified normally. It's pretty clear, but can be missed at the first sight.

The second one is even more obvious - the assignment in TestClass's constructor doesn't initialize the local collection with values from the Constants class - it just assigns the reference to exactly the same collection. So, as the assigned collection can be modified and we've just assigned it to our TestsClass instance, we already have the doors open to modify the "constant" collection by mistake.

And finally, what the Json.NET deserializer is doing here? The documentation states: "By default Json.NET will attempt to set JSON values onto existing objects and add JSON values to existing collections during deserialization.". It means that when the collection instance for TheCollection property was already created by the constructor (well, actually not created but "borrowed" from Constants class), Json.NET doesn't create a new one and just appends deserialized values to the existing collection, modifying our NotSupposedToBeModified collection.

Well, the first two pitfalls are pretty easy, but I wouldn't expect the third one. Fortunately, Json.NET provides an easy way to customize its behavior in this matter using ObjectCreationHandling option. One simple addition in DeserializeObject method and we have two green tests (even if the first two issues are still there):

result = JsonConvert.DeserializeObject<TestClass>(
@"{""TheCollection"":[""other""]}",
new JsonSerializerSettings() { ObjectCreationHandling = ObjectCreationHandling.Replace });

Friday, February 17, 2012

Mapping-by-Code & Fluent NHibernate issues summary

In my mapping-by-code posts series I've just completed, I reviewed the capabilities of both mapping-by-code and Fluent NHibernate in comparison to plain old XML mappings. There are some more or less serious bugs on both sides, as well as both solutions don't offer everything XML does. In each case, when I found the issue worth mentioning, I was looking if it was already reported and reported it myself if not. Here is the quick summary:

Mapping-by-Code

Fluent NHibernate


As you can see, the number of issues I've encountered is very similiar for both mapping-by-code and Fluent NHibernate. For mapping-by-code, majority of them were already reported and actions were taken. Actually, 5 of them are already resolved and wait for NH 3.3 release. I've reported 3 new issues (one of which was fixed in few days) and extended another one.

For Fluent NHibernate, I've reported 8 issues out of 10 encountered. Sadly, by now, none of them were even commented. It looks like there's no active development on FNH. I tend to agree that leaving issues in no man's land with no status at all is a sign of a neglected community. I'd prefer to have these issues closed with "won't do" status than ignored, for sure.

Wednesday, February 15, 2012

NHibernate's mapping-by-code - the summary

Six weeks ago, when I started my experiments with NHibernate's 3.2 new mapping feature - mapping-by-code, I was a loyal Fluent NHibernate user and a fan of method chains in APIs. My first impression about mapping-by-code was that it seems to be a good direction, but it's still immature and - what's important - not documented at all. I decided to have a deeper look and it turned into almost twenty parts series exploring all the possible mappings - probably the only complete guide to mapping-by-code on the web so far. Time to sum the series up.

Let's start with what mapping-by-code is. It is an XML-less mapping solution being an integral part of NHibernate since 3.2, based on ConfORM library. Its API tries to conform to XML naming and structure. There's a strong convention in how the mapping methods are built. Its names are almost always equal to XML elements names. The first parameter points to the mapped property, second is for its options corresponding XML attributes (and XML <key> element, if applicable) and the rest of parameters, if any, corresponds to nested XML elements. It's very convenient for those familiar with XML schema or for documentation readers.

Mapping-by-code also came with very powerful mapping by convention tool - ConventionModelMapper. It is highly flexible and customizable, but customizing it may not even be needed, as by default it is able to figure out mappings even for components or maps. The only thing it can't map automatically are bidirectional relationships - but it was pretty easy to fix this using conventions (I've updated my conventions since first published - it now supports all kinds of collections, inheritance and more - feel free to use it).

Here is the full table of contents of my mapping-by-code series.

  1. First impressions
  2. Naming convention resembling Fluent
  3. Property
  4. Component
  5. ManyToOne
  6. inheritance
  7. dynamic component
  8. Set and Bag
  9. OneToMany and other collection-based relation types
  10. concurrency
  11. OneToOne
  12. Join
  13. Any
  14. List, Array, IdBag
  15. Map
  16. Id, NaturalId
  17. composite identifiers
  18. entity-level mappings

And what about Fluent NHibernate? Hiding the XML was a great idea, but simplifying the mappings went too far, in my opinion. I've already mentioned the mess caused by concept name changes made in Fluent NHibernate (1) (2) - I wouldn't repeat it again. Moreover, XML mapping is a tree structure and it just doesn't fit into single method chains. Fluent NHibernate's API bypasses this limitations by prefixing method names (like KeyColumn) or by falling back to the interface that uses Action<T> (i.e. in Join or Component mapping), quite similiar to mapping-by-code API. Method chaining also makes it hard to reuse the same concepts in different contexts. It's lot easier in mapping-by-code way - i.e. Column mapping is the same in every mapped feature and it is handled by exactly the same code.

Don't get me wrong. I think FNH was a good and useful project. But I've used it as the only existing alternative to cumbersome and verbose XML mapping. And now, when we have an alternative that is integrated into NHibernate (no external dependency and versioning issues), more efficient (no XML serialization) and with better API (no ambiguity, NH naming kept), the purpose of FNH's existence is highly reduced.

Monday, February 13, 2012

Mapping-by-Code - entity-level mappings

We're finally reaching the end of mapping-by-code series. In the last post about mapping possibilities I will cover all options mapped directly at the entity level, that do not map to a column in the database. They define different entity behaviors and customization options and majority of them translates to elements or attributes in XML <class> mapping. Let's go through these possibilities.

Table("tableName");
Schema("schemaName");
Catalog("catalogName");

These are pretty obvious ones - they define where in the database the entity is represented.

EntityName("entityName");
DynamicInsert(true);
DynamicUpdate(true);
BatchSize(10);
Lazy(true);
SelectBeforeUpdate(true);
Mutable(true);
Synchronize("table1", "table2");
SchemaAction(NHibernate.Mapping.ByCode.SchemaAction.All); // or .Drop, .Export, .None, .Update, .Validate
  • EntityName allows to define an alias for the entity - useful when we're mapping the same class more than once.
  • DynamicInsert and DynamicUpdate decide whether to restrict constructed SQL queries only to properties modified explicitly (by default - with these options turned off - NHibernate inserts/updates all properties everytime).
  • BatchSize is an last resort solution for Select N+1 problem - it sets up batching when loading entities in a loop.
  • Lazy(false) completely turns off lazy loading for the entity (no proxy is created).
  • SelectBeforeUpdate is to fetch the data before update, surprisingly - another way of dealing with concurrency.
  • Mutable(false) reduces the NHibernate's infrastructure when the entity is read-only for our application (i.e. when mapped to a database view or to a lookup-only table).
  • Synchronize informs NHibernate that the entity is derived from another and it should care not to return stale data when querying the derived entity.
  • SchemaAction is for hbm2ddl tool to decide what should it do when creating session factory.
Cache(c =>
{
c.Usage(CacheUsage.NonstrictReadWrite); // or .ReadOnly, .ReadWrite, .Transactional
c.Include(CacheInclude.All); // or .NonLazy
c.Region("regionName");
});

Cache is for second-level caching. We need to turn it on explicitly for every entity we want to cache by defining Usage model at least.

Filter("filterName", f => f.Condition("filter SQL condition"));
Where("SQL condition");

Filter and Where are two different ways of narrowing the scope of entities loaded and managed by NHibernate.

SqlInsert("custom SQL");
SqlUpdate("custom SQL");
SqlDelete("custom SQL");
Subselect("custom SQL");

These four are for customizing CRUD operations on the entity. Useful i.e. when access to the table should be done through the stored procedures only.

Loader("loaderReference");
Persister<CustomPersister>();
Proxy(typeof(ProxyType));

And these three are even more low-level possibilities for customization. Haven't explored it thoroughly, but I don't think there are lot of scenarios when they are needed.

There are some XML attributes that do not have an equivalent in mapping-by-code yet. These are tuplizer, resultset, abstract, polymorphism, optimistic-lock, check, rowid, node and import. Apart from optimistic-lock, they don't look important.

Fluent NHibernate's equivalents

FNH offers a bit different subset of entity-level options. Some of mapping-by-code deficiencies are covered (like OptimisticLock, Polymorphism, ImportType, CheckConstraint, Tuplizer), some features are missing instead (like Catalog, Synchronize, Loader). Here are the options available:

Table("tableName");
Schema("schemaName");

EntityName("entityName");
DynamicInsert();
DynamicUpdate();
BatchSize(10);
LazyLoad();
OptimisticLock.All(); // or .Dirty, .None, .Version
SelectBeforeUpdate();
ReadOnly();
Polymorphism.Explicit(); // or .Implicit
SchemaAction.All(); // or .Drop, .Export, .Update, .Validate, .Custom

Cache.IncludeAll() // or .IncludeNonLazy
.Region("regionName")
.NonStrictReadWrite(); // or .ReadOnly, .ReadWrite, .Transactional, .CustomUsage<>

ApplyFilter("filterName", "SQL condition");
Where("SQL condition");

CheckConstraint("check");
ImportType<Import>().As("alternativeName");

SqlInsert("sql query").Check.None(); // or .RowCount
SqlUpdate("sql query");
SqlDelete("sql query");
SqlDeleteAll("sql query");
Subselect("sql query");
StoredProcedure("command", "sql query").Check.None();

Persister<CustomPersister>();
Proxy(typeof(ProxyType));
Tuplizer(TuplizerMode.Xml, typeof(Tuplizer));

There are some name changes when compared to XML attributes or elements names. LazyLoad is for lazy, CheckConstraint for check, ReadOnly for mutable="false" and ApplyFilter covers filter element. StoredProcedure is used internally within SqlXYZ elements - I don't know why this method is in public API. There is also one elements that should not be there - SqlDeleteAll do not have an equivalent in XML mapping and can't be used.


And that's all for mappings exploration! I'll probably summarize the series in a separate post or two.

Friday, February 10, 2012

Mapping-by-Code - composite identifiers

Recently we've talked about surrogate primary keys. Let's move on to different foreign key types supported by NHibernate. We have composite keys available in two different ways, depending on whether we have the key represented in object model as a component (ComponentAsId) or just as several properties in the entity (ComposedId).

ComponentAsId(x => x.Key, m =>
{
m.Property(x => x.KeyPart);
// etc.
});

ComposedId(m =>
{
m.Property(x => x.KeyPart);
// other key parts
});

ComponentAsId is an equivalent of <composite-id> XML element with name and class attributes. ComposedId is an equivalent of <composite-id> without attributes. Both in ComponentAsId and ComposedId we need to specify properties taking part in the key and we do it in a standard way, known i.e. from Component mapping. In both cases a way to specify unsaved-value and mapped attributes is missing.

ComponentAsId is unfortunately broken in NHibernate 3.2 - it ignores the property name pointing to key component. It will be fixed in 3.3, in the meantime we have to use XML mapping here or modify the HbmMapping class directly, like this:

mapping.RootClasses.Single(x => x.Name == typeof(EntityWithComponentAsId).Name).CompositeId.name = "Key";

Fluent NHibernate's equivalents

Composite identifiers are supported well, too, in both variants.

// ComposedId equivalent
CompositeId()
.KeyProperty(x => x.KeyPart)
.KeyReference(x => x.KeyReference)
.UnsavedValue("string?")
.Access.Field();

// ComponentAsId equivalent
CompositeId(x => x.Key)
.KeyProperty(k => k.KeyPart)
.KeyReference(k => k.KeyReference)
.Not.Mapped()
.UnsavedValue("string?")
.Access.Field();

We have KeyProperty as an equivalent of key-property element in XML (mapped with Property in mapping-by-code). We have KeyReference for key-many-to-one (mapped with ManyToOne in mapping-by-code). We have Mapped method as an direct equivalent of mapped attribute from XML as well as UnsavedValue method for unsaved-value attribute (but why it is string-typed?).

There's also one more method in chain - ComponentCompositeIdentifier. It seems to be an alternative syntax for ComponentAsId case, but I couldn't make it produce valid XML mapping and the functionality is already covered, so I'll ignore it.

Wednesday, February 8, 2012

Mapping-by-Code - Id, NaturalId

I've already finished going through all the Ayende's posts about NHibernate mappings and analysing its mapping-by-code equivalents, but I feel I haven't covered everything. The first quite obvious NHibernate's feature Ayende skipped is primary key mapping. There are several options available - from identity columns, native generators, through HiLo and sequences, up to composite identifiers. As always, I'm not going to explain how each of them works, I'll keep focus on mapping-by-code and Fluent NHibernate's possibilities.

The most common primary key mapping is available through Id method.

Id(x => x.Id, m =>
{
m.Column("id");

m.Generator(Generators.Native, g => g.Params(new
{
// generator-specific options
}));

m.Length(10);
m.Type(new Int32Type());
m.Access(Accessor.Field);
});

There are several features missing - like unsaved-value (will be added in NHibernate 3.3) or DDL column options.

Probably the most important option is Generator. It specifies the way NHibernate (or database) generates unique values. There are 8 predefined types of generators available through static Generators class:

public static class Generators
{
// assigning the values is client code responsibility
public static IGeneratorDef Assigned { get; }

// whatever is native in underlying database
public static IGeneratorDef Native { get; }

// High-Low
public static IGeneratorDef HighLow { get; }

// Guid
public static IGeneratorDef Guid { get; }

// sequential Guid
public static IGeneratorDef GuidComb { get; }

// database-level sequence
public static IGeneratorDef Sequence { get; }

// database-level identity
public static IGeneratorDef Identity { get; }

// driven by referenced entity
public static IGeneratorDef Foreign<TEntity>(Expression<Func<TEntity, object>> property);
public static IGeneratorDef Foreign(MemberInfo property);
}

Some of those can have additional parameters specified using Generator method second parameter and anonymous type inside Params call. This is probably the only place in mapping-by-code when we have not strongly-typed options, but it's not worse than in XML.

Here are the parameters available for HighLow, as well as its default values:

m.Generator(Generators.HighLow, g => g.Params(new
{
max_lo = Int16.MaxValue, // size of ids range reserved at once - Int16.MaxValue by default
table = "hibernate_unique_key",
schema = null,
catalog = null,
column = "next_hi",
where = "", // additional SQL condition applied to query when fetching next_hi value
}));

And here is the similiar list for Sequence:

m.Generator(Generators.Sequence, g => g.Params(new
{
sequence = "hibernate_sequence",
schema = null,
catalog = null,
parameters = null, // driver-specific DDL string to be appended to create command
}));

There's another id-related option available - natural ID. It is in fact not a primary key handling option, but it's related, so I decided to include it here. It is available through NaturalId mapping method.

NaturalId(m =>
{
m.Property(x => x.KeyPropery);
// etc...
});

Mutable attribute from XML natural-id element has no equivalent in mapping-by-code.

Fluent NHibernate's equivalents

For mapping surrogate keys there is Id method chain available. Let's see first which of the generators are available directly:

Id(x => x.Id)
.GeneratedBy.Assigned()
.GeneratedBy.Custom<CustomGenerator>()
.GeneratedBy.Foreign("propertyName")
.GeneratedBy.Guid()
.GeneratedBy.GuidComb()
.GeneratedBy.GuidNative()
.GeneratedBy.HiLo("table", "column", "maxLo", "where")
.GeneratedBy.Identity()
.GeneratedBy.Increment()
.GeneratedBy.Native("sequenceName")
.GeneratedBy.Select()
.GeneratedBy.SeqHiLo("sequenceName", "maxLo")
.GeneratedBy.Sequence("sequenceName")
.GeneratedBy.SequenceIdentity("sequenceName")
.GeneratedBy.TriggerIdentity()
.GeneratedBy.UuidHex("format")
.GeneratedBy.UuidString();

All the parameters are optional. Apart from that, there is an additional configuration interface available in most generators:

p => p.AddParam("name", "value")

As we can see, the number of options available directly is higher than in mapping-by-code.

Time to look at different id mapping options.

Id(x => x.Id)
.Column("id")
.Length(10)
.CustomType<CustomType>()
.Access.Field()
.UnsavedValue(0)
.Check("sql constraint")
.CustomSqlType("sqlType")
.Default(0)
.Index("idx")
.Nullable()
.Precision(10)
.Scale(10)
.Unique()
.UniqueKey("uniq");

There are a lot more options available in FNH than in mapping-by-code. I think that at least some of them are completely useless (like defining unique key name), but this is not a FNH's bug, this is what NHibernate mapping does allow, surprisingly.

NaturalId is supported well, too.

NaturalId()
.Property(x => x.Name, "columnName")
.Reference(x => x.Test, "referenceColumnName")
// etc.
.Not.ReadOnly();

Column names are optional. There's no way to set other column options. And ReadOnly is FNH name for mutable attribute.

Monday, February 6, 2012

Mapping-by-Code - Map

The last not yet covered collection type supported in NHibernate 3.2 mapping-by-code is Map. I'll skip all the options that are common with set and bag and refer to its own post. For other collection types, see also the previous post.

Map is NHibernate's name for dictionary, or key-value collection. It is quite a powerful feature. NHibernate allows keys and values to be of different types - either single elements (like strings), components or entities. We can have an entity in the key and string in the value or string in the key and component in the value, etc. Moreover, as with every other collection, map can take part in one-to-many, many-to-many and even many-to-any relationships. There's quite a lot of options.

Mapping for all of these options must be scary, one may think. But not with mapping-by-code. I'm really impressed how easy, convenient and consistent with all the other features the Map mapping is. There's an recurring pattern in mapping-by-code that each nested element in XML has its corresponding options as a separate method parameter. And that's the case for Map, too. There are three basic overloads for Map method:

public void Map<TKey, TElement>(
Expression<Func<TEntity, IDictionary<TKey, TElement>>> property,
Action<IMapPropertiesMapper<TEntity, TKey, TElement>> collectionMapping);

public void Map<TKey, TElement>(
Expression<Func<TEntity, IDictionary<TKey, TElement>>> property,
Action<IMapPropertiesMapper<TEntity, TKey, TElement>> collectionMapping,
Action<ICollectionElementRelation<TElement>> mapping);

public void Map<TKey, TElement>(
Expression<Func<TEntity, IDictionary<TKey, TElement>>> property,
Action<IMapPropertiesMapper<TEntity, TKey, TElement>> collectionMapping,
Action<IMapKeyRelation<TKey>> keyMapping,
Action<ICollectionElementRelation<TElement>> mapping);

Don't be scared. These are just three variants of the same method ordered from the simplest one (with two parameters skipped - it'll have its default values) to the most complete one (with all four parameters). Let's focus on the last one.

The first parameter is - as always - the lambda expression pointing to a generic IDictionary property we are mapping. The second is an obligatory collection mapping - all the standard collection options (described in the post about Bag and Set) are available there. The third one, optional, is to set options for dictionary key mapping and the last one, also optional, is about its value mapping. Here it is, with all its options:

Map(x => x.Features, c =>
{
// standard collection options here
}, k =>
{
k.Element(e =>
{
e.Column("indexColumnName");
// or
e.Column(c =>
{
c.Name("indexColumnName");
// etc...
});

e.Formula("arbitrary SQL expression");
e.Length(10);
e.Type<CustomType>();
});
// or
k.Component(e =>
{
e.Property(x => x.KeyElement);
e.ManyToOne(x => x.OtherKeyElement);
// etc...
});
// or
k.ManyToMany(e =>
{
e.Column("indexColumnName");
// or
e.Column(c =>
{
c.Name("indexColumnName");
// etc...
});

e.ForeignKey("foreignKeyName");
e.Formula("arbitrary SQL expression");
});
}, r =>
{
// one of the following:
r.OneToMany();
r.Element();
r.Component(m => {});
r.ManyToMany();
r.ManyToAny<CommonIdType>(m => {});
});

Let's talk about key and value mappings (third and fourth parameter). In XML, there are plenty of different names for all its options, like map-key, composite-map-key, map-key-many-to-many etc. Mapping-by-code simplifies it drastically. We just need to choose what type of element our key is - either Element (for simple values), Component or ManyToMany (for cases when we have an entity as a key). We are already familiar with all the options inside. The same is for value mapping - we need to choose one of five possible relation types, depending on what do we have as a value in our dictionary. For the description of different relation types, see separate post - all the options are available here, too.

Moreover, the default ConventionModelMapper is smart enough to figure out most options just by looking at our model and in most cases we just don't need to specify the relation types and its options at all.

Fluent NHibernate's equivalent

In Fluent NHibernate, the name "Map" was already used for Property mapping. Instead we have several different methods in HasMany/HasManyToMany chains to be used - AsMap, AsEntityMap, AsSimpleAssociation, AsTernaryAssociation. Pretty hard to figure out what's what.

Mapping for the dictionary value and its options stays the same as in Bag/Set case. I'll focus on mapping different key types.

The first case is when we have simple value as a key - like IDictionary<string, string>:

HasMany(x => x.Dictionary)
.AsMap<string>("keyColumn")
.Element("valueColumn");

Majority of AsMap overloads want me to specify lambda expression pointing from the value to the key and internally use AsIndexedCollection method (designed for List, I believe). These methods seems to assume that key is a part of an object in value, what is strange a bit. In that case we don't really need to have a dictionary and we could just map that collection as a simple bag.

Moreover, FNH is not trying to determine the key type on its own - we need to specify it as a generic parameter in AsMap method explicitly, otherwise we'll end up with int. I also can't see the way to set other key options available in mapping-by-code, i.e. Length or Formula.

The second case I've tried was having a component as a key - and I've failed. I was looking through the Web and the source code itself and I can't see no composite-index equivalent.

Third type of objects allowed as a key is another entity - i.e. IDictionary<Entity, string>. We can map it using AsEntityMap:

HasMany(x => x.Dictionary)
.AsEntityMap()
.Element("valueColumn");

I was looking for any clues when should I use AsTernaryAssociation or AsSimpleAssociation directly, but I don't find any.

To sum things up, dictionary mapping in Fluent NHibernate is a horrible mess. I've found a comment in FNH source code: "I'm not proud of this. The fluent interface for maps really needs to be rethought. But I've let maps sit unsupported for way too long so a hack is better than nothing." Well, personally I'm not sure whether it'll be better in this case. Mapping by code is way much better this time.

Friday, February 3, 2012

Mapping-by-Code - List, Array, IdBag

Time to complete the subject of collection mappings - there are some features unique for lists and idbags that need to be mentioned. I'll skip all the options that are common with set and bag and refer to its own post.

List is an explicitly ordered collection. It has an additional option in the mapping for the index column that keeps the ordering, with the standard Column options mapping inside.

List(x => x.Districts, c =>
{
c.Index(idx =>
{
idx.Base(1);
idx.Column("indexColumnName");
// or
idx.Column(ic =>
{
ic.Name("indexColumnName");
// etc...
});
});
});

There are two other rarely used ordered collections in NHibernate - arrays and primitive arrays. Both are not supported in mapping-by-code. But I don't think it's a big deal.

Another collection type is IdBag. It is generally a bag enriched with additional identity column - useful for many-to-many intermediate tables, when we don't want to have composite primary key there. The only new option in the mapping is Id method, with several options available:

IdBag(x => x.Collection, c =>
{
c.Id(i =>
{
i.Column("idColumn");
i.Generator(Generators.Native);
i.Length(100);
i.Type(new Int32Type());
});
}, r => r.ManyToMany());

Fluent NHibernate's equivalents

As we already know, FNH defines collection mappings as a part of relation mapping chain. I'll skip all the options already covered in the Bag/Set post.

List is mapped using AsList method. There is a possibility to set index column name and type - other DDL options, as well as base attribute are missing.

HasMany(x => x.Users)
.AsList(idx => idx.Column("indexColumnName").Type<int>())

Array is also supported, contrary to mapping-by-code. It has similiar possibilities to the list mapping, the only difference is that we can define index column name by lambda parameter, but it's used only if we don't specify it in the second parameter explicitly.

HasMany(x => x.Users)
.AsArray(x => x.Name, idx => idx.Column("indexColumnName").Type<string>())

Primitive arrays and idbags are not supported.

Thursday, February 2, 2012

Mapping-by-Code - Any

Probably the last relation type supported by NHibernate we have left is any relationship. It is quite an exotic feature. Let's re-use Ayende's model again:

Any lets us to map many-to-one relationship that has entities of different types on the "one" side. There's no foreign keys defined on the database side and the relation logic is maintained on the object level only. To make it work, we need to tell NHibernate what types of entities we expect and how to distinguish it. Here's how to do it in mapping-by-code, with all the options available:

Any(x => x.Payment, typeof(long), m =>
{
m.IdType<long>();
m.MetaType<string>();
m.MetaValue("CreditCard", typeof(CreditCardPayment));
m.MetaValue("Wire", typeof(WirePayment));

m.Columns(id =>
{
id.Name("PaymentId");
id.NotNullable(true);
// etc...
}, classRef =>
{
classRef.Name("PaymentType");
classRef.NotNullable(true);
// etc...
});

m.Access(Accessor.Field);
m.Lazy(true);
m.Cascade(Cascade.Persist);
m.Index("payment_idx");
m.Insert(true);
m.Update(true);
m.OptimisticLock(true);
});

The first parameter is - as always - a lambda pointing to the mapped property. The second defines the common type for identifiers of all entities at the other side. Third one is for mapping options, which are pretty similiar to already mentioned ManyToAny relationship.

Inside the configuration we need to define properties for two columns - one to keep the other entity identifier, second to keep its discriminating value. We do it using Columns method's parameters. Later we have to specify the type of discriminator using MetaType method and its generic argument - string is good here. We can also specify the common type of identifiers using IdType method, but we've already did it in Any second parameter (I think that this method is useless here). The last thing we need to do is to define the list of entity types that are allowed at other side of the relation and its corresponding discriminator values. In order to do this, we call MetaValue method - its first parameter is the discriminator value, second is the type. There are also several standard options available, like Lazy and Cascade.

Fluent NHibernate's equivalent

Contrary to many-to-any, any is supported well in Fluent NHibernate.

ReferencesAny(x => x.Test)
.IdentityType<long>()
.MetaType<string>()
.AddMetaValue<CreditCardPayment>("CreditCard")
.AddMetaValue<WirePayment>("Wire")
.EntityIdentifierColumn("PaymentId")
.EntityTypeColumn("PaymentType")
.Access.Field()
.LazyLoad()
.Cascade.All()
.Insert()
.Update()
.OptimisticLock();

There is no Index method and we can't set options other than name for database columns. Apart from that, the rest is pretty clear and easy.


The next post in Ayende's series was about many-to-any, but I've covered it within collections and relation types, so I'm going to skip it.